From 6397e809aace8dcf7a0c8b12087cbb927ca5516d Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 18 Jan 2016 10:25:41 +0100 Subject: [PATCH 001/139] 8146395: Add inline qualifier in oop.hpp and fix inlining in gc files Fix remaining issues after 8146401. Also fix windows VS2010 linkage problem (g1OopClosures.hpp). Reviewed-by: stefank, mgerdin --- .../share/vm/gc/cms/cmsCollectorPolicy.cpp | 3 +- .../src/share/vm/gc/cms/cmsOopClosures.hpp | 46 ++++++------- .../share/vm/gc/cms/cmsOopClosures.inline.hpp | 61 ++++++++++++----- .../vm/gc/cms/compactibleFreeListSpace.cpp | 6 +- .../vm/gc/cms/compactibleFreeListSpace.hpp | 6 +- .../gc/cms/concurrentMarkSweepGeneration.cpp | 4 +- .../src/share/vm/gc/cms/parNewGeneration.cpp | 4 +- hotspot/src/share/vm/gc/cms/promotionInfo.cpp | 27 +++++++- hotspot/src/share/vm/gc/cms/promotionInfo.hpp | 27 +------- hotspot/src/share/vm/gc/g1/concurrentMark.hpp | 18 +---- .../share/vm/gc/g1/concurrentMark.inline.hpp | 19 +++++- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 4 +- hotspot/src/share/vm/gc/g1/g1OopClosures.hpp | 26 +++---- .../share/vm/gc/g1/g1OopClosures.inline.hpp | 10 ++- hotspot/src/share/vm/gc/g1/g1RemSet.cpp | 1 + .../vm/gc/g1/g1SATBCardTableModRefBS.cpp | 4 +- .../vm/gc/g1/g1SATBCardTableModRefBS.hpp | 27 ++------ .../gc/g1/g1SATBCardTableModRefBS.inline.hpp | 58 ++++++++++++++++ .../src/share/vm/gc/parallel/asPSYoungGen.cpp | 4 +- .../vm/gc/parallel/cardTableExtension.cpp | 3 +- .../share/vm/gc/parallel/objectStartArray.cpp | 5 +- .../share/vm/gc/parallel/objectStartArray.hpp | 21 +----- .../gc/parallel/objectStartArray.inline.hpp | 53 +++++++++++++++ .../share/vm/gc/parallel/parMarkBitMap.cpp | 4 +- .../vm/gc/parallel/parallelScavengeHeap.cpp | 5 +- hotspot/src/share/vm/gc/parallel/psOldGen.cpp | 3 +- .../vm/gc/parallel/psParallelCompact.cpp | 13 +++- .../vm/gc/parallel/psParallelCompact.hpp | 29 ++------ .../gc/parallel/psParallelCompact.inline.hpp | 10 +++ .../src/share/vm/gc/parallel/psScavenge.cpp | 13 +++- .../src/share/vm/gc/parallel/psScavenge.hpp | 9 +-- .../share/vm/gc/serial/defNewGeneration.cpp | 1 + hotspot/src/share/vm/gc/shared/ageTable.cpp | 7 +- hotspot/src/share/vm/gc/shared/ageTable.hpp | 8 +-- .../share/vm/gc/shared/ageTable.inline.hpp | 36 ++++++++++ .../vm/gc/shared/collectedHeap.inline.hpp | 3 +- .../src/share/vm/gc/shared/genOopClosures.hpp | 16 ++--- .../vm/gc/shared/genOopClosures.inline.hpp | 15 +++- .../share/vm/gc/shared/referenceProcessor.cpp | 2 +- .../share/vm/gc/shared/referenceProcessor.hpp | 33 ++------- .../gc/shared/referenceProcessor.inline.hpp | 68 +++++++++++++++++++ hotspot/src/share/vm/gc/shared/space.hpp | 10 +-- .../src/share/vm/gc/shared/space.inline.hpp | 11 ++- .../src/share/vm/memory/heapInspection.cpp | 10 ++- .../src/share/vm/memory/heapInspection.hpp | 10 +-- hotspot/src/share/vm/oops/markOop.inline.hpp | 3 +- hotspot/src/share/vm/oops/objArrayOop.hpp | 2 +- .../src/share/vm/oops/objArrayOop.inline.hpp | 2 +- hotspot/src/share/vm/oops/oop.hpp | 22 +++--- hotspot/src/share/vm/oops/oop.inline.hpp | 22 +++--- 50 files changed, 515 insertions(+), 289 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.inline.hpp create mode 100644 hotspot/src/share/vm/gc/parallel/objectStartArray.inline.hpp create mode 100644 hotspot/src/share/vm/gc/shared/ageTable.inline.hpp create mode 100644 hotspot/src/share/vm/gc/shared/referenceProcessor.inline.hpp diff --git a/hotspot/src/share/vm/gc/cms/cmsCollectorPolicy.cpp b/hotspot/src/share/vm/gc/cms/cmsCollectorPolicy.cpp index 6e49af09f71..0333b4f433e 100644 --- a/hotspot/src/share/vm/gc/cms/cmsCollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/cms/cmsCollectorPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 +35,7 @@ #include "gc/shared/space.hpp" #include "gc/shared/vmGCOperations.hpp" #include "memory/universe.hpp" +#include "oops/oop.inline.hpp" #include "runtime/arguments.hpp" #include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" diff --git a/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp index e85dc681e3b..165ab17e682 100644 --- a/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp +++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,15 +40,9 @@ class MarkFromRootsClosure; class ParMarkFromRootsClosure; // Decode the oop and call do_oop on it. -#define DO_OOP_WORK_DEFN \ - void do_oop(oop obj); \ - template inline void do_oop_work(T* p) { \ - T heap_oop = oopDesc::load_heap_oop(p); \ - if (!oopDesc::is_null(heap_oop)) { \ - oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); \ - do_oop(obj); \ - } \ - } +#define DO_OOP_WORK_DEFN \ + void do_oop(oop obj); \ + template inline void do_oop_work(T* p); // TODO: This duplication of the MetadataAwareOopClosure class is only needed // because some CMS OopClosures derive from OopsInGenClosure. It would be @@ -131,8 +125,8 @@ class PushAndMarkClosure: public MetadataAwareOopClosure { bool concurrent_precleaning); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { PushAndMarkClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; // In the parallel case, the bit map and the @@ -157,8 +151,8 @@ class ParPushAndMarkClosure: public MetadataAwareOopClosure { OopTaskQueue* work_queue); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { ParPushAndMarkClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { ParPushAndMarkClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; // The non-parallel version (the parallel version appears further below). @@ -186,8 +180,8 @@ class MarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure { bool concurrent_precleaning); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); void set_freelistLock(Mutex* m) { _freelistLock = m; @@ -220,8 +214,8 @@ class ParMarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure { OopTaskQueue* work_queue); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { ParMarkRefsIntoAndScanClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { ParMarkRefsIntoAndScanClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); void trim_queue(uint size); }; @@ -249,8 +243,8 @@ class PushOrMarkClosure: public MetadataAwareOopClosure { MarkFromRootsClosure* parent); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); // Deal with a stack overflow condition void handle_stack_overflow(HeapWord* lost); @@ -287,8 +281,8 @@ class ParPushOrMarkClosure: public MetadataAwareOopClosure { ParMarkFromRootsClosure* parent); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { ParPushOrMarkClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { ParPushOrMarkClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); // Deal with a stack overflow condition void handle_stack_overflow(HeapWord* lost); @@ -318,8 +312,8 @@ class CMSKeepAliveClosure: public MetadataAwareOopClosure { bool concurrent_precleaning() const { return _concurrent_precleaning; } virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; class CMSInnerParMarkAndPushClosure: public MetadataAwareOopClosure { @@ -336,8 +330,8 @@ class CMSInnerParMarkAndPushClosure: public MetadataAwareOopClosure { OopTaskQueue* work_queue); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; // A parallel (MT) version of the above, used when diff --git a/hotspot/src/share/vm/gc/cms/cmsOopClosures.inline.hpp b/hotspot/src/share/vm/gc/cms/cmsOopClosures.inline.hpp index 363097543c8..500989691e5 100644 --- a/hotspot/src/share/vm/gc/cms/cmsOopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,21 +30,6 @@ #include "gc/shared/taskqueue.inline.hpp" #include "oops/oop.inline.hpp" -// Trim our work_queue so its length is below max at return -inline void ParMarkRefsIntoAndScanClosure::trim_queue(uint max) { - while (_work_queue->size() > max) { - oop newOop; - if (_work_queue->pop_local(newOop)) { - assert(newOop->is_oop(), "Expected an oop"); - assert(_bit_map->isMarked((HeapWord*)newOop), - "only grey objects on this stack"); - // iterate over the oops in this oop, marking and pushing - // the ones in CMS heap (i.e. in _span). - newOop->oop_iterate(&_parPushAndMarkClosure); - } - } -} - // MetadataAwareOopClosure and MetadataAwareOopsInGenClosure are duplicated, // until we get rid of OopsInGenClosure. @@ -61,4 +46,48 @@ inline void MetadataAwareOopsInGenClosure::do_cld_nv(ClassLoaderData* cld) { cld->oops_do(_klass_closure._oop_closure, &_klass_closure, claim); } +// Decode the oop and call do_oop on it. +#define DO_OOP_WORK_IMPL(cls) \ + template void cls::do_oop_work(T* p) { \ + T heap_oop = oopDesc::load_heap_oop(p); \ + if (!oopDesc::is_null(heap_oop)) { \ + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); \ + do_oop(obj); \ + } \ + } + +#define DO_OOP_WORK_NV_IMPL(cls) \ + DO_OOP_WORK_IMPL(cls) \ + void cls::do_oop_nv(oop* p) { cls::do_oop_work(p); } \ + void cls::do_oop_nv(narrowOop* p) { cls::do_oop_work(p); } + +DO_OOP_WORK_IMPL(MarkRefsIntoClosure) +DO_OOP_WORK_IMPL(ParMarkRefsIntoClosure) +DO_OOP_WORK_IMPL(MarkRefsIntoVerifyClosure) +DO_OOP_WORK_NV_IMPL(PushAndMarkClosure) +DO_OOP_WORK_NV_IMPL(ParPushAndMarkClosure) +DO_OOP_WORK_NV_IMPL(MarkRefsIntoAndScanClosure) +DO_OOP_WORK_NV_IMPL(ParMarkRefsIntoAndScanClosure) + +// Trim our work_queue so its length is below max at return +inline void ParMarkRefsIntoAndScanClosure::trim_queue(uint max) { + while (_work_queue->size() > max) { + oop newOop; + if (_work_queue->pop_local(newOop)) { + assert(newOop->is_oop(), "Expected an oop"); + assert(_bit_map->isMarked((HeapWord*)newOop), + "only grey objects on this stack"); + // iterate over the oops in this oop, marking and pushing + // the ones in CMS heap (i.e. in _span). + newOop->oop_iterate(&_parPushAndMarkClosure); + } + } +} + +DO_OOP_WORK_NV_IMPL(PushOrMarkClosure) +DO_OOP_WORK_NV_IMPL(ParPushOrMarkClosure) +DO_OOP_WORK_NV_IMPL(CMSKeepAliveClosure) +DO_OOP_WORK_NV_IMPL(CMSInnerParMarkAndPushClosure) +DO_OOP_WORK_IMPL(CMSParKeepAliveClosure) + #endif // SHARE_VM_GC_CMS_CMSOOPCLOSURES_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index 6c9a4ea4fae..ca352451e9e 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,6 +219,10 @@ void CompactibleFreeListSpace::initializeIndexedFreeListArray() { } } +size_t CompactibleFreeListSpace::obj_size(const HeapWord* addr) const { + return adjustObjectSize(oop(addr)->size()); +} + void CompactibleFreeListSpace::resetIndexedFreeListArray() { for (size_t i = 1; i < IndexSetSize; i++) { assert(_indexedFreeList[i].size() == (size_t) i, diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index c9f9af242be..eeaa07ce280 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -313,9 +313,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { return adjustObjectSize(size); } - inline size_t obj_size(const HeapWord* addr) const { - return adjustObjectSize(oop(addr)->size()); - } + inline size_t obj_size(const HeapWord* addr) const; protected: // Reset the indexed free list to its initial empty condition. diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index f852e9d0017..b41a088faa3 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3324,6 +3324,8 @@ class ParConcMarkingClosure: public MetadataAwareOopClosure { } }; +DO_OOP_WORK_IMPL(ParConcMarkingClosure) + // Grey object scanning during work stealing phase -- // the salient assumption here is that any references // that are in these stolen objects being scanned must diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp index 9918dd00edc..7dbdebe0f04 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ #include "gc/cms/parOopClosures.inline.hpp" #include "gc/serial/defNewGeneration.inline.hpp" #include "gc/shared/adaptiveSizePolicy.hpp" -#include "gc/shared/ageTable.hpp" +#include "gc/shared/ageTable.inline.hpp" #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/gcHeapSummary.hpp" #include "gc/shared/gcTimer.hpp" diff --git a/hotspot/src/share/vm/gc/cms/promotionInfo.cpp b/hotspot/src/share/vm/gc/cms/promotionInfo.cpp index a7a5a3b1fd3..92c5725361f 100644 --- a/hotspot/src/share/vm/gc/cms/promotionInfo.cpp +++ b/hotspot/src/share/vm/gc/cms/promotionInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,31 @@ ///////////////////////////////////////////////////////////////////////// +PromotedObject* PromotedObject::next() const { + assert(!((FreeChunk*)this)->is_free(), "Error"); + PromotedObject* res; + if (UseCompressedOops) { + // The next pointer is a compressed oop stored in the top 32 bits + res = (PromotedObject*)oopDesc::decode_heap_oop(_data._narrow_next); + } else { + res = (PromotedObject*)(_next & next_mask); + } + assert(oop(res)->is_oop_or_null(true /* ignore mark word */), "Expected an oop or NULL at " PTR_FORMAT, p2i(oop(res))); + return res; +} + +inline void PromotedObject::setNext(PromotedObject* x) { + assert(((intptr_t)x & ~next_mask) == 0, "Conflict in bit usage, " + "or insufficient alignment of objects"); + if (UseCompressedOops) { + assert(_data._narrow_next == 0, "Overwrite?"); + _data._narrow_next = oopDesc::encode_heap_oop(oop(x)); + } else { + _next |= (intptr_t)x; + } + assert(!((FreeChunk*)this)->is_free(), "Error"); +} + ////////////////////////////////////////////////////////////////////////////// // We go over the list of promoted objects, removing each from the list, // and applying the closure (this may, in turn, add more elements to diff --git a/hotspot/src/share/vm/gc/cms/promotionInfo.hpp b/hotspot/src/share/vm/gc/cms/promotionInfo.hpp index d42a8dbd119..387da17ed95 100644 --- a/hotspot/src/share/vm/gc/cms/promotionInfo.hpp +++ b/hotspot/src/share/vm/gc/cms/promotionInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,29 +64,8 @@ class PromotedObject VALUE_OBJ_CLASS_SPEC { Data _data; }; public: - inline PromotedObject* next() const { - assert(!((FreeChunk*)this)->is_free(), "Error"); - PromotedObject* res; - if (UseCompressedOops) { - // The next pointer is a compressed oop stored in the top 32 bits - res = (PromotedObject*)oopDesc::decode_heap_oop(_data._narrow_next); - } else { - res = (PromotedObject*)(_next & next_mask); - } - assert(oop(res)->is_oop_or_null(true /* ignore mark word */), "Expected an oop or NULL at " PTR_FORMAT, p2i(oop(res))); - return res; - } - inline void setNext(PromotedObject* x) { - assert(((intptr_t)x & ~next_mask) == 0, "Conflict in bit usage, " - "or insufficient alignment of objects"); - if (UseCompressedOops) { - assert(_data._narrow_next == 0, "Overwrite?"); - _data._narrow_next = oopDesc::encode_heap_oop(oop(x)); - } else { - _next |= (intptr_t)x; - } - assert(!((FreeChunk*)this)->is_free(), "Error"); - } + PromotedObject* next() const; + void setNext(PromotedObject* x); inline void setPromotedMark() { _next |= promoted_mask; assert(!((FreeChunk*)this)->is_free(), "Error"); diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc/g1/concurrentMark.hpp index 5d195e51cb1..5c8f81e78df 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,12 +96,7 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { } // The argument addr should be the start address of a valid object - HeapWord* nextObject(HeapWord* addr) { - oop obj = (oop) addr; - HeapWord* res = addr + obj->size(); - assert(offsetToHeapWord(heapWordToOffset(res)) == res, "sanity"); - return res; - } + inline HeapWord* nextObject(HeapWord* addr); void print_on_error(outputStream* st, const char* prefix) const; @@ -627,14 +622,7 @@ public: // If marking is not in progress, it's a no-op. void verify_no_cset_oops() PRODUCT_RETURN; - bool isPrevMarked(oop p) const { - assert(p != NULL && p->is_oop(), "expected an oop"); - HeapWord* addr = (HeapWord*)p; - assert(addr >= _prevMarkBitMap->startWord() || - addr < _prevMarkBitMap->endWord(), "in a region"); - - return _prevMarkBitMap->isMarked(addr); - } + inline bool isPrevMarked(oop p) const; inline bool do_yield_check(uint worker_i = 0); diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp index fe26975cc20..d2695f59c70 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -185,6 +185,14 @@ inline bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { return true; } +// The argument addr should be the start address of a valid object +HeapWord* CMBitMapRO::nextObject(HeapWord* addr) { + oop obj = (oop) addr; + HeapWord* res = addr + obj->size(); + assert(offsetToHeapWord(heapWordToOffset(res)) == res, "sanity"); + return res; +} + #define check_mark(addr) \ assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \ "outside underlying space?"); \ @@ -353,6 +361,15 @@ inline void ConcurrentMark::markPrev(oop p) { ((CMBitMap*)_prevMarkBitMap)->mark((HeapWord*) p); } +bool ConcurrentMark::isPrevMarked(oop p) const { + assert(p != NULL && p->is_oop(), "expected an oop"); + HeapWord* addr = (HeapWord*)p; + assert(addr >= _prevMarkBitMap->startWord() || + addr < _prevMarkBitMap->endWord(), "in a region"); + + return _prevMarkBitMap->isMarked(addr); +} + inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, uint worker_id, HeapRegion* hr) { assert(obj != NULL, "pre-condition"); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index accba8f5bd7..9faa2774b7e 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/generationSpec.hpp" #include "gc/shared/isGCActiveMark.hpp" -#include "gc/shared/referenceProcessor.hpp" +#include "gc/shared/referenceProcessor.inline.hpp" #include "gc/shared/taskqueue.inline.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp index 2ba19e33d6c..d8c449fb603 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -206,9 +206,9 @@ class G1Mux2Closure : public OopClosure { OopClosure* _c2; public: G1Mux2Closure(OopClosure *c1, OopClosure *c2); - template void do_oop_work(T* p); - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } + template inline void do_oop_work(T* p); + virtual inline void do_oop(oop* p); + virtual inline void do_oop(narrowOop* p); }; // A closure that returns true if it is actually applied @@ -219,9 +219,9 @@ class G1TriggerClosure : public OopClosure { public: G1TriggerClosure(); bool triggered() const { return _triggered; } - template void do_oop_work(T* p); - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } + template inline void do_oop_work(T* p); + virtual inline void do_oop(oop* p); + virtual inline void do_oop(narrowOop* p); }; // A closure which uses a triggering closure to determine @@ -232,9 +232,9 @@ class G1InvokeIfNotTriggeredClosure: public OopClosure { OopClosure* _oop_cl; public: G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t, OopClosure* oc); - template void do_oop_work(T* p); - virtual void do_oop(oop* p) { do_oop_work(p); } - virtual void do_oop(narrowOop* p) { do_oop_work(p); } + template inline void do_oop_work(T* p); + virtual inline void do_oop(oop* p); + virtual inline void do_oop(narrowOop* p); }; class G1UpdateRSOrPushRefOopClosure: public OopClosure { @@ -263,9 +263,9 @@ public: return result; } - template void do_oop_work(T* p); - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop(oop* p) { do_oop_work(p); } + template inline void do_oop_work(T* p); + virtual inline void do_oop(narrowOop* p); + virtual inline void do_oop(oop* p); }; #endif // SHARE_VM_GC_G1_G1OOPCLOSURES_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index b65002af6b4..bdc18c62bcc 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * 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,12 +141,16 @@ inline void G1Mux2Closure::do_oop_work(T* p) { _c1->do_oop(p); _c2->do_oop(p); } +void G1Mux2Closure::do_oop(oop* p) { do_oop_work(p); } +void G1Mux2Closure::do_oop(narrowOop* p) { do_oop_work(p); } template inline void G1TriggerClosure::do_oop_work(T* p) { // Record that this closure was actually applied (triggered). _triggered = true; } +void G1TriggerClosure::do_oop(oop* p) { do_oop_work(p); } +void G1TriggerClosure::do_oop(narrowOop* p) { do_oop_work(p); } template inline void G1InvokeIfNotTriggeredClosure::do_oop_work(T* p) { @@ -154,6 +158,8 @@ inline void G1InvokeIfNotTriggeredClosure::do_oop_work(T* p) { _oop_cl->do_oop(p); } } +void G1InvokeIfNotTriggeredClosure::do_oop(oop* p) { do_oop_work(p); } +void G1InvokeIfNotTriggeredClosure::do_oop(narrowOop* p) { do_oop_work(p); } template inline void G1UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { @@ -224,6 +230,8 @@ inline void G1UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { to->rem_set()->add_reference(p, _worker_i); } } +void G1UpdateRSOrPushRefOopClosure::do_oop(oop* p) { do_oop_work(p); } +void G1UpdateRSOrPushRefOopClosure::do_oop(narrowOop* p) { do_oop_work(p); } template void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) { diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 9258d575a95..40e3959c886 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -34,6 +34,7 @@ #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1RemSet.inline.hpp" +#include "gc/g1/g1SATBCardTableModRefBS.inline.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp index 5cd8b594e8e..c701b700c6a 100644 --- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/g1SATBCardTableModRefBS.hpp" +#include "gc/g1/g1SATBCardTableModRefBS.inline.hpp" #include "gc/g1/heapRegion.hpp" #include "gc/g1/satbMarkQueue.hpp" #include "gc/shared/memset_with_concurrent_readers.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp index d08d36f43ca..d07d6c507b0 100644 --- a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,20 +58,11 @@ public: // We export this to make it available in cases where the static // type of the barrier set is known. Note that it is non-virtual. - template inline void inline_write_ref_field_pre(T* field, oop newVal) { - T heap_oop = oopDesc::load_heap_oop(field); - if (!oopDesc::is_null(heap_oop)) { - enqueue(oopDesc::decode_heap_oop(heap_oop)); - } - } + template inline void inline_write_ref_field_pre(T* field, oop newVal); // These are the more general virtual versions. - virtual void write_ref_field_pre_work(oop* field, oop new_val) { - inline_write_ref_field_pre(field, new_val); - } - virtual void write_ref_field_pre_work(narrowOop* field, oop new_val) { - inline_write_ref_field_pre(field, new_val); - } + inline virtual void write_ref_field_pre_work(oop* field, oop new_val); + inline virtual void write_ref_field_pre_work(narrowOop* field, oop new_val); virtual void write_ref_field_pre_work(void* field, oop new_val) { guarantee(false, "Not needed"); } @@ -98,15 +89,7 @@ public: return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val(); } - void set_card_claimed(size_t card_index) { - jbyte val = _byte_map[card_index]; - if (val == clean_card_val()) { - val = (jbyte)claimed_card_val(); - } else { - val |= (jbyte)claimed_card_val(); - } - _byte_map[card_index] = val; - } + inline void set_card_claimed(size_t card_index); void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN; void g1_mark_as_young(const MemRegion& mr); diff --git a/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.inline.hpp b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.inline.hpp new file mode 100644 index 00000000000..ae81d54cdee --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1SATBCardTableModRefBS.inline.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#ifndef SHARE_VM_GC_G1_G1SATBCARDTABLEMODREFBS_INLINE_HPP +#define SHARE_VM_GC_G1_G1SATBCARDTABLEMODREFBS_INLINE_HPP + +#include "gc/g1/g1SATBCardTableModRefBS.hpp" +#include "oops/oop.inline.hpp" + +// We export this to make it available in cases where the static +// type of the barrier set is known. Note that it is non-virtual. +template void G1SATBCardTableModRefBS::inline_write_ref_field_pre(T* field, oop newVal) { + T heap_oop = oopDesc::load_heap_oop(field); + if (!oopDesc::is_null(heap_oop)) { + enqueue(oopDesc::decode_heap_oop(heap_oop)); + } +} + +// These are the more general virtual versions. +void G1SATBCardTableModRefBS::write_ref_field_pre_work(oop* field, oop new_val) { + inline_write_ref_field_pre(field, new_val); +} +void G1SATBCardTableModRefBS::write_ref_field_pre_work(narrowOop* field, oop new_val) { + inline_write_ref_field_pre(field, new_val); +} + +void G1SATBCardTableModRefBS::set_card_claimed(size_t card_index) { + jbyte val = _byte_map[card_index]; + if (val == clean_card_val()) { + val = (jbyte)claimed_card_val(); + } else { + val |= (jbyte)claimed_card_val(); + } + _byte_map[card_index] = val; +} + +#endif // SHARE_VM_GC_G1_G1SATBCARDTABLEMODREFBS_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/parallel/asPSYoungGen.cpp b/hotspot/src/share/vm/gc/parallel/asPSYoungGen.cpp index 130e51ab5d5..b0fea5ba6fe 100644 --- a/hotspot/src/share/vm/gc/parallel/asPSYoungGen.cpp +++ b/hotspot/src/share/vm/gc/parallel/asPSYoungGen.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ #include "gc/parallel/asPSYoungGen.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" #include "gc/parallel/psMarkSweepDecorator.hpp" -#include "gc/parallel/psScavenge.hpp" +#include "gc/parallel/psScavenge.inline.hpp" #include "gc/parallel/psYoungGen.hpp" #include "gc/shared/gcUtil.hpp" #include "gc/shared/spaceDecorator.hpp" diff --git a/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp b/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp index 083fb2a2fb0..d4be1aa0639 100644 --- a/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp +++ b/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc/parallel/cardTableExtension.hpp" #include "gc/parallel/gcTaskManager.hpp" +#include "gc/parallel/objectStartArray.inline.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" #include "gc/parallel/psPromotionManager.inline.hpp" #include "gc/parallel/psScavenge.hpp" diff --git a/hotspot/src/share/vm/gc/parallel/objectStartArray.cpp b/hotspot/src/share/vm/gc/parallel/objectStartArray.cpp index 81d9d1bb833..ef871aad915 100644 --- a/hotspot/src/share/vm/gc/parallel/objectStartArray.cpp +++ b/hotspot/src/share/vm/gc/parallel/objectStartArray.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "gc/parallel/objectStartArray.hpp" +#include "gc/parallel/objectStartArray.inline.hpp" #include "gc/shared/cardTableModRefBS.hpp" #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" @@ -123,7 +123,6 @@ void ObjectStartArray::reset() { memset(_blocks_region.start(), clean_block, _blocks_region.byte_size()); } - bool ObjectStartArray::object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const { assert(start_addr <= end_addr, diff --git a/hotspot/src/share/vm/gc/parallel/objectStartArray.hpp b/hotspot/src/share/vm/gc/parallel/objectStartArray.hpp index 3c51c4e12d0..3b801c8f63d 100644 --- a/hotspot/src/share/vm/gc/parallel/objectStartArray.hpp +++ b/hotspot/src/share/vm/gc/parallel/objectStartArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,23 +139,7 @@ class ObjectStartArray : public CHeapObj { // a given block. The blocks contain the offset of the last // object in that block. Scroll backwards by one, and the first // object hit should be at the beginning of the block - HeapWord* object_start(HeapWord* addr) const { - assert_covered_region_contains(addr); - jbyte* block = block_for_addr(addr); - HeapWord* scroll_forward = offset_addr_for_block(block--); - while (scroll_forward > addr) { - scroll_forward = offset_addr_for_block(block--); - } - - HeapWord* next = scroll_forward; - while (next <= addr) { - scroll_forward = next; - next += oop(next)->size(); - } - assert(scroll_forward <= addr, "wrong order for current and arg"); - assert(addr <= next, "wrong order for arg and next"); - return scroll_forward; - } + inline HeapWord* object_start(HeapWord* addr) const; bool is_block_allocated(HeapWord* addr) { assert_covered_region_contains(addr); @@ -165,7 +149,6 @@ class ObjectStartArray : public CHeapObj { return true; } -#undef assert_covered_region_contains // Return true if an object starts in the range of heap addresses. // If an object starts at an address corresponding to diff --git a/hotspot/src/share/vm/gc/parallel/objectStartArray.inline.hpp b/hotspot/src/share/vm/gc/parallel/objectStartArray.inline.hpp new file mode 100644 index 00000000000..53d9fea5fd6 --- /dev/null +++ b/hotspot/src/share/vm/gc/parallel/objectStartArray.inline.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#ifndef SHARE_VM_GC_PARALLEL_OBJECTSTARTARRAY_INLINE_HPP +#define SHARE_VM_GC_PARALLEL_OBJECTSTARTARRAY_INLINE_HPP + +#include "gc/parallel/objectStartArray.hpp" + +// Optimized for finding the first object that crosses into +// a given block. The blocks contain the offset of the last +// object in that block. Scroll backwards by one, and the first +// object hit should be at the beginning of the block +HeapWord* ObjectStartArray::object_start(HeapWord* addr) const { + assert_covered_region_contains(addr); + jbyte* block = block_for_addr(addr); + HeapWord* scroll_forward = offset_addr_for_block(block--); + while (scroll_forward > addr) { + scroll_forward = offset_addr_for_block(block--); + } + + HeapWord* next = scroll_forward; + while (next <= addr) { + scroll_forward = next; + next += oop(next)->size(); + } + assert(scroll_forward <= addr, "wrong order for current and arg"); + assert(addr <= next, "wrong order for arg and next"); + return scroll_forward; +} + + +#endif // SHARE_VM_GC_PARALLEL_OBJECTSTARTARRAY_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp index 0e6ec57b18c..2965749e981 100644 --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "gc/parallel/parMarkBitMap.hpp" -#include "gc/parallel/psParallelCompact.hpp" +#include "gc/parallel/psParallelCompact.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" diff --git a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp index cfe23356b5a..76d2e0abd2d 100644 --- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,11 @@ #include "gc/parallel/cardTableExtension.hpp" #include "gc/parallel/gcTaskManager.hpp" #include "gc/parallel/generationSizer.hpp" +#include "gc/parallel/objectStartArray.inline.hpp" #include "gc/parallel/parallelScavengeHeap.inline.hpp" #include "gc/parallel/psAdaptiveSizePolicy.hpp" #include "gc/parallel/psMarkSweep.hpp" -#include "gc/parallel/psParallelCompact.hpp" +#include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/psPromotionManager.hpp" #include "gc/parallel/psScavenge.hpp" #include "gc/parallel/vmPSOperations.hpp" diff --git a/hotspot/src/share/vm/gc/parallel/psOldGen.cpp b/hotspot/src/share/vm/gc/parallel/psOldGen.cpp index 0a89c5f9d22..f567fe03e9a 100644 --- a/hotspot/src/share/vm/gc/parallel/psOldGen.cpp +++ b/hotspot/src/share/vm/gc/parallel/psOldGen.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc/parallel/objectStartArray.inline.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" #include "gc/parallel/psAdaptiveSizePolicy.hpp" #include "gc/parallel/psMarkSweepDecorator.hpp" diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index 2198705943a..d26948de533 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3169,3 +3169,14 @@ UpdateOnlyClosure::do_addr(HeapWord* addr, size_t words) { do_addr(addr); return ParMarkBitMap::incomplete; } + +ParMarkBitMapClosure::IterationStatus +FillClosure::do_addr(HeapWord* addr, size_t size) { + CollectedHeap::fill_with_objects(addr, size); + HeapWord* const end = addr + size; + do { + _start_array->allocate_block(addr); + addr += oop(addr)->size(); + } while (addr < end); + return ParMarkBitMap::incomplete; +} diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp index 76e55666d34..cac1823ce14 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1242,16 +1242,6 @@ class PSParallelCompact : AllStatic { #endif // #ifdef ASSERT }; -inline bool PSParallelCompact::mark_obj(oop obj) { - const int obj_size = obj->size(); - if (mark_bitmap()->mark_obj(obj, obj_size)) { - _summary_data.add_obj(obj, obj_size); - return true; - } else { - return false; - } -} - inline bool PSParallelCompact::is_marked(oop obj) { return mark_bitmap()->is_marked(obj); } @@ -1386,9 +1376,8 @@ class UpdateOnlyClosure: public ParMarkBitMapClosure { inline void do_addr(HeapWord* addr); }; -class FillClosure: public ParMarkBitMapClosure -{ -public: +class FillClosure: public ParMarkBitMapClosure { + public: FillClosure(ParCompactionManager* cm, PSParallelCompact::SpaceId space_id) : ParMarkBitMapClosure(PSParallelCompact::mark_bitmap(), cm), _start_array(PSParallelCompact::start_array(space_id)) @@ -1397,17 +1386,9 @@ public: "cannot use FillClosure in the young gen"); } - virtual IterationStatus do_addr(HeapWord* addr, size_t size) { - CollectedHeap::fill_with_objects(addr, size); - HeapWord* const end = addr + size; - do { - _start_array->allocate_block(addr); - addr += oop(addr)->size(); - } while (addr < end); - return ParMarkBitMap::incomplete; - } + virtual IterationStatus do_addr(HeapWord* addr, size_t size); -private: + private: ObjectStartArray* const _start_array; }; diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp index 43063fd154e..2fcc947132f 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp @@ -31,6 +31,16 @@ #include "oops/klass.hpp" #include "oops/oop.inline.hpp" +inline bool PSParallelCompact::mark_obj(oop obj) { + const int obj_size = obj->size(); + if (mark_bitmap()->mark_obj(obj, obj_size)) { + _summary_data.add_obj(obj, obj_size); + return true; + } else { + return false; + } +} + template inline void PSParallelCompact::adjust_pointer(T* p) { T heap_oop = oopDesc::load_heap_oop(p); diff --git a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp index 6b9e9318b0b..acc12d0ce95 100644 --- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp +++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include "gc/parallel/parallelScavengeHeap.hpp" #include "gc/parallel/psAdaptiveSizePolicy.hpp" #include "gc/parallel/psMarkSweep.hpp" -#include "gc/parallel/psParallelCompact.hpp" +#include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/psScavenge.inline.hpp" #include "gc/parallel/psTasks.hpp" #include "gc/shared/collectorPolicy.hpp" @@ -763,6 +763,15 @@ GCTaskManager* const PSScavenge::gc_task_manager() { return ParallelScavengeHeap::gc_task_manager(); } +// Adaptive size policy support. When the young generation/old generation +// boundary moves, _young_generation_boundary must be reset +void PSScavenge::set_young_generation_boundary(HeapWord* v) { + _young_generation_boundary = v; + if (UseCompressedOops) { + _young_generation_boundary_compressed = (uintptr_t)oopDesc::encode_heap_oop((oop)v); + } +} + void PSScavenge::initialize() { // Arguments must have been parsed diff --git a/hotspot/src/share/vm/gc/parallel/psScavenge.hpp b/hotspot/src/share/vm/gc/parallel/psScavenge.hpp index dfabc1b81bc..3fb235f043d 100644 --- a/hotspot/src/share/vm/gc/parallel/psScavenge.hpp +++ b/hotspot/src/share/vm/gc/parallel/psScavenge.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,12 +117,7 @@ class PSScavenge: AllStatic { } // Adaptive size policy support. When the young generation/old generation // boundary moves, _young_generation_boundary must be reset - static void set_young_generation_boundary(HeapWord* v) { - _young_generation_boundary = v; - if (UseCompressedOops) { - _young_generation_boundary_compressed = (uintptr_t)oopDesc::encode_heap_oop((oop)v); - } - } + static void set_young_generation_boundary(HeapWord* v); // Called by parallelScavengeHeap to init the tenuring threshold static void initialize(); diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index e86037cc5d9..9c00cd90383 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/serial/defNewGeneration.inline.hpp" +#include "gc/shared/ageTable.inline.hpp" #include "gc/shared/cardTableRS.hpp" #include "gc/shared/collectorCounters.hpp" #include "gc/shared/gcHeapSummary.hpp" diff --git a/hotspot/src/share/vm/gc/shared/ageTable.cpp b/hotspot/src/share/vm/gc/shared/ageTable.cpp index cf6542ddf11..f741061e591 100644 --- a/hotspot/src/share/vm/gc/shared/ageTable.cpp +++ b/hotspot/src/share/vm/gc/shared/ageTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,15 +23,16 @@ */ #include "precompiled.hpp" -#include "gc/shared/ageTable.hpp" +#include "gc/shared/ageTable.inline.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectorPolicy.hpp" #include "gc/shared/gcPolicyCounters.hpp" #include "memory/resourceArea.hpp" #include "logging/log.hpp" +#include "oops/oop.inline.hpp" #include "utilities/copy.hpp" -/* Copyright (c) 1992, 2015, Oracle and/or its affiliates, and Stanford University. +/* Copyright (c) 1992, 2016, Oracle and/or its affiliates, and Stanford University. See the LICENSE file for license information. */ AgeTable::AgeTable(bool global) { diff --git a/hotspot/src/share/vm/gc/shared/ageTable.hpp b/hotspot/src/share/vm/gc/shared/ageTable.hpp index b0724101642..4af836f8acd 100644 --- a/hotspot/src/share/vm/gc/shared/ageTable.hpp +++ b/hotspot/src/share/vm/gc/shared/ageTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ class GCPolicyCounters; -/* Copyright (c) 1992, 2015, Oracle and/or its affiliates, and Stanford University. +/* Copyright (c) 1992, 2016, Oracle and/or its affiliates, and Stanford University. See the LICENSE file for license information. */ // Age table for adaptive feedback-mediated tenuring (scavenging) @@ -56,9 +56,7 @@ class AgeTable VALUE_OBJ_CLASS_SPEC { void clear(); // add entry - void add(oop p, size_t oop_size) { - add(p->age(), oop_size); - } + inline void add(oop p, size_t oop_size); void add(uint age, size_t oop_size) { assert(age > 0 && age < table_size, "invalid age of object"); diff --git a/hotspot/src/share/vm/gc/shared/ageTable.inline.hpp b/hotspot/src/share/vm/gc/shared/ageTable.inline.hpp new file mode 100644 index 00000000000..aaa7470d927 --- /dev/null +++ b/hotspot/src/share/vm/gc/shared/ageTable.inline.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#ifndef SHARE_VM_GC_SHARED_AGETABLE_INLINE_HPP +#define SHARE_VM_GC_SHARED_AGETABLE_INLINE_HPP + +#include "gc/shared/ageTable.hpp" +#include "oops/oop.inline.hpp" + +// add entry +void AgeTable::add(oop p, size_t oop_size) { + add(p->age(), oop_size); +} + +#endif // SHARE_VM_GC_SHARED_AGETABLE_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp index ef4de405437..449f252d1d4 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "gc/shared/threadLocalAllocBuffer.inline.hpp" #include "memory/universe.hpp" #include "oops/arrayOop.hpp" +#include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" diff --git a/hotspot/src/share/vm/gc/shared/genOopClosures.hpp b/hotspot/src/share/vm/gc/shared/genOopClosures.hpp index 05009cc1372..f1dd89344d8 100644 --- a/hotspot/src/share/vm/gc/shared/genOopClosures.hpp +++ b/hotspot/src/share/vm/gc/shared/genOopClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,23 +146,15 @@ class FilteringClosure: public ExtendedOopClosure { HeapWord* _boundary; ExtendedOopClosure* _cl; protected: - template inline void do_oop_work(T* p) { - T heap_oop = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(heap_oop)) { - oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if ((HeapWord*)obj < _boundary) { - _cl->do_oop(p); - } - } - } + template inline void do_oop_work(T* p); public: FilteringClosure(HeapWord* boundary, ExtendedOopClosure* cl) : ExtendedOopClosure(cl->ref_processor()), _boundary(boundary), _cl(cl) {} virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); - inline void do_oop_nv(oop* p) { FilteringClosure::do_oop_work(p); } - inline void do_oop_nv(narrowOop* p) { FilteringClosure::do_oop_work(p); } + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); virtual bool do_metadata() { return do_metadata_nv(); } inline bool do_metadata_nv() { assert(!_cl->do_metadata(), "assumption broken, must change to 'return _cl->do_metadata()'"); return false; } }; diff --git a/hotspot/src/share/vm/gc/shared/genOopClosures.inline.hpp b/hotspot/src/share/vm/gc/shared/genOopClosures.inline.hpp index ea570baa68f..13883f2283a 100644 --- a/hotspot/src/share/vm/gc/shared/genOopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/genOopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 +124,19 @@ template inline void FastScanClosure::do_oop_work(T* p) { inline void FastScanClosure::do_oop_nv(oop* p) { FastScanClosure::do_oop_work(p); } inline void FastScanClosure::do_oop_nv(narrowOop* p) { FastScanClosure::do_oop_work(p); } +template void FilteringClosure::do_oop_work(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if ((HeapWord*)obj < _boundary) { + _cl->do_oop(p); + } + } +} + +void FilteringClosure::do_oop_nv(oop* p) { FilteringClosure::do_oop_work(p); } +void FilteringClosure::do_oop_nv(narrowOop* p) { FilteringClosure::do_oop_work(p); } + // Note similarity to ScanClosure; the difference is that // the barrier set is taken care of outside this closure. template inline void ScanWeakRefClosure::do_oop_work(T* p) { diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 73be2d60d14..544cf81001d 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -30,7 +30,7 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/referencePolicy.hpp" -#include "gc/shared/referenceProcessor.hpp" +#include "gc/shared/referenceProcessor.inline.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "oops/oop.inline.hpp" diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp index 0d100893465..b7656845c72 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp @@ -58,23 +58,13 @@ class AbstractRefProcTaskExecutor; class DiscoveredList { public: DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } - oop head() const { - return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : - _oop_head; - } + inline oop head() const; HeapWord* adr_head() { return UseCompressedOops ? (HeapWord*)&_compressed_head : (HeapWord*)&_oop_head; } - void set_head(oop o) { - if (UseCompressedOops) { - // Must compress the head ptr. - _compressed_head = oopDesc::encode_heap_oop(o); - } else { - _oop_head = o; - } - } - bool is_empty() const { return head() == NULL; } + inline void set_head(oop o); + inline bool is_empty() const; size_t length() { return _len; } void set_length(size_t len) { _len = len; } void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } @@ -113,22 +103,7 @@ private: public: inline DiscoveredListIterator(DiscoveredList& refs_list, OopClosure* keep_alive, - BoolObjectClosure* is_alive): - _refs_list(refs_list), - _prev_next(refs_list.adr_head()), - _prev(NULL), - _ref(refs_list.head()), -#ifdef ASSERT - _first_seen(refs_list.head()), -#endif -#ifndef PRODUCT - _processed(0), - _removed(0), -#endif - _next(NULL), - _keep_alive(keep_alive), - _is_alive(is_alive) -{ } + BoolObjectClosure* is_alive); // End Of List. inline bool has_next() const { return _ref != NULL; } diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.inline.hpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.inline.hpp new file mode 100644 index 00000000000..51e96921803 --- /dev/null +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.inline.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#ifndef SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_INLINE_HPP +#define SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_INLINE_HPP + +#include "gc/shared/referenceProcessor.hpp" +#include "oops/oop.inline.hpp" + +oop DiscoveredList::head() const { + return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : + _oop_head; +} + +void DiscoveredList::set_head(oop o) { + if (UseCompressedOops) { + // Must compress the head ptr. + _compressed_head = oopDesc::encode_heap_oop(o); + } else { + _oop_head = o; + } +} + +bool DiscoveredList::is_empty() const { + return head() == NULL; +} + +DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_list, + OopClosure* keep_alive, + BoolObjectClosure* is_alive): + _refs_list(refs_list), + _prev_next(refs_list.adr_head()), + _prev(NULL), + _ref(refs_list.head()), +#ifdef ASSERT + _first_seen(refs_list.head()), +#endif +#ifndef PRODUCT + _processed(0), + _removed(0), +#endif + _next(NULL), + _keep_alive(keep_alive), + _is_alive(is_alive) { +} + +#endif // SHARE_VM_GC_SHARED_REFERENCEPROCESSOR_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/shared/space.hpp b/hotspot/src/share/vm/gc/shared/space.hpp index c44383d18f3..465dca90eb6 100644 --- a/hotspot/src/share/vm/gc/shared/space.hpp +++ b/hotspot/src/share/vm/gc/shared/space.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -360,9 +360,7 @@ private: return size; } - inline size_t obj_size(const HeapWord* addr) const { - return oop(addr)->size(); - } + inline size_t obj_size(const HeapWord* addr) const; public: CompactibleSpace() : @@ -508,9 +506,7 @@ class ContiguousSpace: public CompactibleSpace { return true; // Always true, since scan_limit is top } - inline size_t scanned_block_size(const HeapWord* addr) const { - return oop(addr)->size(); - } + inline size_t scanned_block_size(const HeapWord* addr) const; protected: HeapWord* _top; diff --git a/hotspot/src/share/vm/gc/shared/space.inline.hpp b/hotspot/src/share/vm/gc/shared/space.inline.hpp index af6f1a8bfb2..7b27598e286 100644 --- a/hotspot/src/share/vm/gc/shared/space.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/space.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,10 @@ OffsetTableContigSpace::block_start_const(const void* p) const { return _offsets.block_start(p); } +size_t CompactibleSpace::obj_size(const HeapWord* addr) const { + return oop(addr)->size(); +} + template inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { // Compute the new addresses for the live objects and store it in the mark @@ -331,4 +335,9 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { if (ZapUnusedHeapArea) space->mangle_unused_area(); } } + +size_t ContiguousSpace::scanned_block_size(const HeapWord* addr) const { + return oop(addr)->size(); +} + #endif // SHARE_VM_GC_SHARED_SPACE_INLINE_HPP diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index d120a45218f..a116650946c 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,14 @@ // HeapInspection +int KlassSizeStats::count(oop x) { + return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); +} + +int KlassSizeStats::count_array(objArrayOop x) { + return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); +} + inline KlassInfoEntry::~KlassInfoEntry() { if (_subclasses != NULL) { delete _subclasses; diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 97197b1bc5e..7d2acbdb7c9 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,13 +154,9 @@ public: HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD) - static int count(oop x) { - return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); - } + static int count(oop x); - static int count_array(objArrayOop x) { - return (HeapWordSize * (((x) != NULL) ? (x)->size() : 0)); - } + static int count_array(objArrayOop x); template static int count(T* x) { return (HeapWordSize * ((x) ? (x)->size() : 0)); diff --git a/hotspot/src/share/vm/oops/markOop.inline.hpp b/hotspot/src/share/vm/oops/markOop.inline.hpp index 94ab6eb1848..77d2fee0ebb 100644 --- a/hotspot/src/share/vm/oops/markOop.inline.hpp +++ b/hotspot/src/share/vm/oops/markOop.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "oops/klass.hpp" #include "oops/markOop.hpp" +#include "oops/oop.inline.hpp" #include "runtime/globals.hpp" // Should this header be preserved during GC (when biased locking is enabled)? diff --git a/hotspot/src/share/vm/oops/objArrayOop.hpp b/hotspot/src/share/vm/oops/objArrayOop.hpp index b30b1fd8007..dfa8b319fcb 100644 --- a/hotspot/src/share/vm/oops/objArrayOop.hpp +++ b/hotspot/src/share/vm/oops/objArrayOop.hpp @@ -81,7 +81,7 @@ private: // Accessing oop obj_at(int index) const; - void /*inline*/ obj_at_put(int index, oop value); + void inline obj_at_put(int index, oop value); oop atomic_compare_exchange_oop(int index, oop exchange_value, oop compare_value); diff --git a/hotspot/src/share/vm/oops/objArrayOop.inline.hpp b/hotspot/src/share/vm/oops/objArrayOop.inline.hpp index 5c9004de897..56f542da4f5 100644 --- a/hotspot/src/share/vm/oops/objArrayOop.inline.hpp +++ b/hotspot/src/share/vm/oops/objArrayOop.inline.hpp @@ -39,7 +39,7 @@ inline oop objArrayOopDesc::obj_at(int index) const { } } -inline void objArrayOopDesc::obj_at_put(int index, oop value) { +void objArrayOopDesc::obj_at_put(int index, oop value) { if (UseCompressedOops) { oop_store(obj_at_addr(index), value); } else { diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 20e25261d5b..e944e601378 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -82,16 +82,16 @@ class oopDesc { // objects during a GC) -- requires a valid klass pointer inline void init_mark(); - /*inline*/ Klass* klass() const; + inline Klass* klass() const; inline Klass* klass_or_null() const volatile; inline Klass** klass_addr(); inline narrowKlass* compressed_klass_addr(); - /*inline*/ void set_klass(Klass* k); + inline void set_klass(Klass* k); // For klass field compression inline int klass_gap() const; - /*inline*/ void set_klass_gap(int z); + inline void set_klass_gap(int z); // For when the klass pointer is being used as a linked list "next" field. inline void set_klass_to_list_ptr(oop k); inline oop list_ptr_from_klass(); @@ -103,7 +103,7 @@ class oopDesc { inline bool is_a(Klass* k) const; // Returns the actual oop size of the object - /*inline*/ int size(); + inline int size(); // Sometimes (for complicated concurrency-related reasons), it is useful // to be able to figure out the size of an object knowing its klass. @@ -111,7 +111,7 @@ class oopDesc { // type test operations (inlined in oop.inline.hpp) inline bool is_instance() const; - /*inline*/ bool is_array() const; + inline bool is_array() const; inline bool is_objArray() const; inline bool is_typeArray() const; @@ -149,15 +149,15 @@ class oopDesc { // These are overloaded for oop and narrowOop as are the other functions // below so that they can be called in template functions. static inline oop decode_heap_oop_not_null(oop v) { return v; } - static /*inline*/ oop decode_heap_oop_not_null(narrowOop v); + static inline oop decode_heap_oop_not_null(narrowOop v); static inline oop decode_heap_oop(oop v) { return v; } - static /*inline*/ oop decode_heap_oop(narrowOop v); + static inline oop decode_heap_oop(narrowOop v); // Encode an oop pointer to a narrow oop. The or_null versions accept // null oop pointer, others do not in order to eliminate the // null checking branches. static inline narrowOop encode_heap_oop_not_null(oop v); - static /*inline*/ narrowOop encode_heap_oop(oop v); + static inline narrowOop encode_heap_oop(oop v); // Load an oop out of the Java heap as is without decoding. // Called by GC to check for null before decoding. @@ -284,8 +284,8 @@ class oopDesc { inline bool has_bias_pattern() const; // asserts - /*inline*/ bool is_oop(bool ignore_mark_word = false) const; - /*inline*/ bool is_oop_or_null(bool ignore_mark_word = false) const; + inline bool is_oop(bool ignore_mark_word = false) const; + inline bool is_oop_or_null(bool ignore_mark_word = false) const; #ifndef PRODUCT inline bool is_unlocked_oop() const; #endif @@ -312,7 +312,7 @@ class oopDesc { inline oop forwardee() const; // Age of object during scavenge - /*inline*/ uint age() const; + inline uint age() const; inline void incr_age(); // mark-sweep support diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 32b87fa1edd..8390d32501f 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -100,7 +100,7 @@ void oopDesc::init_mark() { set_mark(markOopDesc::prototype_for_object(this)); } -inline Klass* oopDesc::klass() const { +Klass* oopDesc::klass() const { if (UseCompressedClassPointers) { return Klass::decode_klass_not_null(_metadata._compressed_klass); } else { @@ -129,7 +129,7 @@ narrowKlass* oopDesc::compressed_klass_addr() { return &_metadata._compressed_klass; } -inline void oopDesc::set_klass(Klass* k) { +void oopDesc::set_klass(Klass* k) { // since klasses are promoted no store check is needed assert(Universe::is_bootstrapping() || k != NULL, "must be a real Klass*"); assert(Universe::is_bootstrapping() || k->is_klass(), "not a Klass*"); @@ -144,7 +144,7 @@ int oopDesc::klass_gap() const { return *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()); } -inline void oopDesc::set_klass_gap(int v) { +void oopDesc::set_klass_gap(int v) { if (UseCompressedClassPointers) { *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()) = v; } @@ -174,7 +174,7 @@ bool oopDesc::is_a(Klass* k) const { return klass()->is_subtype_of(k); } -inline int oopDesc::size() { +int oopDesc::size() { return size_given_klass(klass()); } @@ -264,7 +264,7 @@ int oopDesc::size_given_klass(Klass* klass) { } bool oopDesc::is_instance() const { return klass()->is_instance_klass(); } -inline bool oopDesc::is_array() const { return klass()->is_array_klass(); } +bool oopDesc::is_array() const { return klass()->is_array_klass(); } bool oopDesc::is_objArray() const { return klass()->is_objArray_klass(); } bool oopDesc::is_typeArray() const { return klass()->is_typeArray_klass(); } @@ -298,7 +298,7 @@ inline bool check_obj_alignment(oop obj) { return cast_from_oop(obj) % MinObjAlignmentInBytes == 0; } -inline oop oopDesc::decode_heap_oop_not_null(narrowOop v) { +oop oopDesc::decode_heap_oop_not_null(narrowOop v) { assert(!is_null(v), "narrow oop value can never be zero"); address base = Universe::narrow_oop_base(); int shift = Universe::narrow_oop_shift(); @@ -307,7 +307,7 @@ inline oop oopDesc::decode_heap_oop_not_null(narrowOop v) { return result; } -inline oop oopDesc::decode_heap_oop(narrowOop v) { +oop oopDesc::decode_heap_oop(narrowOop v) { return is_null(v) ? (oop)NULL : decode_heap_oop_not_null(v); } @@ -325,7 +325,7 @@ narrowOop oopDesc::encode_heap_oop_not_null(oop v) { return (narrowOop)result; } -inline narrowOop oopDesc::encode_heap_oop(oop v) { +narrowOop oopDesc::encode_heap_oop(oop v) { return (is_null(v)) ? (narrowOop)0 : encode_heap_oop_not_null(v); } @@ -516,7 +516,7 @@ bool oopDesc::has_bias_pattern() const { } // used only for asserts -inline bool oopDesc::is_oop(bool ignore_mark_word) const { +bool oopDesc::is_oop(bool ignore_mark_word) const { oop obj = (oop) this; if (!check_obj_alignment(obj)) return false; if (!Universe::heap()->is_in_reserved(obj)) return false; @@ -538,7 +538,7 @@ inline bool oopDesc::is_oop(bool ignore_mark_word) const { // used only for asserts -inline bool oopDesc::is_oop_or_null(bool ignore_mark_word) const { +bool oopDesc::is_oop_or_null(bool ignore_mark_word) const { return this == NULL ? true : is_oop(ignore_mark_word); } @@ -620,7 +620,7 @@ oop oopDesc::forwardee() const { } // The following method needs to be MT safe. -inline uint oopDesc::age() const { +uint oopDesc::age() const { assert(!is_forwarded(), "Attempt to read age from forwarded mark"); if (has_displaced_mark()) { return displaced_mark()->age(); From b0a724f03da81da11c356b9830b2cffa54130fd0 Mon Sep 17 00:00:00 2001 From: Alexander Kulyakhtin Date: Tue, 19 Jan 2016 19:19:51 +0300 Subject: [PATCH 002/139] 8147609: [TESTBUG] Correct the @build statements in the serviceability/dcmd/gc/HeapDumpAllTest.java and HeapDumpTest.java tests Corrected the @build statements Reviewed-by: jbachorik --- hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java | 4 ++-- hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java index bbf073a827c..63e80ab05bd 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 +33,7 @@ * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* * @build jdk.test.lib.hprof.* - * @build jdk.test.lib.hprof.module.* + * @build jdk.test.lib.hprof.model.* * @build jdk.test.lib.hprof.parser.* * @build jdk.test.lib.hprof.utils.* * @build HeapDumpTest diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java index 20f766d3bf6..aefd604c25c 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * 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 @@ import jdk.test.lib.dcmd.PidJcmdExecutor; * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* * @build jdk.test.lib.hprof.* - * @build jdk.test.lib.hprof.module.* + * @build jdk.test.lib.hprof.model.* * @build jdk.test.lib.hprof.parser.* * @build jdk.test.lib.hprof.utils.* * @run testng HeapDumpTest From a73f6dc9402a51d8371a8e2974b48047117d6706 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 20 Jan 2016 11:58:09 -0800 Subject: [PATCH 003/139] 8143608: Don't 64-bit align start of InstanceKlass vtable, itable, and nonstatic_oopmap on 32-bit systems Removed alignment of these fields. Reviewed-by: coleenp, dholmes, mgerdin --- .../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 7 +------ .../src/cpu/sparc/vm/macroAssembler_sparc.cpp | 12 ------------ hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp | 3 --- hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 7 +------ .../sun/jvm/hotspot/oops/InstanceKlass.java | 8 ++++---- hotspot/src/share/vm/oops/arrayKlass.cpp | 6 +----- hotspot/src/share/vm/oops/instanceKlass.cpp | 11 ++++------- hotspot/src/share/vm/oops/instanceKlass.hpp | 16 +++++++--------- 8 files changed, 18 insertions(+), 52 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index c64f1277aab..e3b39b08f39 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -910,11 +910,6 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, // lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); lea(scan_temp, Address(recv_klass, scan_temp, Address::lsl(3))); add(scan_temp, scan_temp, vtable_base); - if (HeapWordsPerLong > 1) { - // Round up to align_object_offset boundary - // see code for instanceKlass::start_of_itable! - round_to(scan_temp, BytesPerLong); - } // Adjust recv_klass by scaled itable_index, so we can free itable_index. assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index 41a38c67418..61122127c96 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -2196,22 +2196,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, // %%% We should store the aligned, prescaled offset in the klassoop. // Then the next several instructions would fold away. - int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); int itb_offset = vtable_base; - if (round_to_unit != 0) { - // hoist first instruction of round_to(scan_temp, BytesPerLong): - itb_offset += round_to_unit - wordSize; - } int itb_scale = exact_log2(vtableEntry::size() * wordSize); sll(scan_temp, itb_scale, scan_temp); add(scan_temp, itb_offset, scan_temp); - if (round_to_unit != 0) { - // Round up to align_object_offset boundary - // see code for InstanceKlass::start_of_itable! - // Was: round_to(scan_temp, BytesPerLong); - // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); - and3(scan_temp, -round_to_unit, scan_temp); - } add(recv_klass, scan_temp, scan_temp); // Adjust recv_klass by scaled itable_index, so we can free itable_index. diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index a8b1c36159e..2f00683bed0 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -3158,9 +3158,6 @@ void TemplateTable::invokeinterface(int byte_no) { Register Rtemp = O1_flags; __ ld(O2_Klass, InstanceKlass::vtable_length_offset() * wordSize, Rtemp); - if (align_object_offset(1) > 1) { - __ round_to(Rtemp, align_object_offset(1)); - } __ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4; if (Assembler::is_simm13(base)) { __ add(Rtemp, base, Rtemp); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index 4381e8aa849..a7a98adb187 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5818,11 +5818,6 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, // %%% Could store the aligned, prescaled offset in the klassoop. lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); - if (HeapWordsPerLong > 1) { - // Round up to align_object_offset boundary - // see code for InstanceKlass::start_of_itable! - round_to(scan_temp, BytesPerLong); - } // Adjust recv_klass by scaled itable_index, so we can free itable_index. assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 75aa05c3954..7e0aa876448 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,7 @@ public class InstanceKlass extends Klass { genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0); majorVersion = new CIntField(type.getCIntegerField("_major_version"), 0); minorVersion = new CIntField(type.getCIntegerField("_minor_version"), 0); - headerSize = Oop.alignObjectOffset(type.getSize()); + headerSize = type.getSize(); // read field offset constants ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue(); @@ -242,8 +242,8 @@ public class InstanceKlass extends Klass { } public long getSize() { - return Oop.alignObjectSize(getHeaderSize() + Oop.alignObjectOffset(getVtableLen()) + - Oop.alignObjectOffset(getItableLen()) + Oop.alignObjectOffset(getNonstaticOopMapSize())); + return Oop.alignObjectSize(getHeaderSize() + getVtableLen() + + getItableLen() + getNonstaticOopMapSize()); } public static long getHeaderSize() { return headerSize; } diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index faa66411c35..573bcab6805 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * 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,11 +42,7 @@ int ArrayKlass::static_size(int header_size) { // If this assert fails, see comments in base_create_array_klass. header_size = InstanceKlass::header_size(); int vtable_len = Universe::base_vtable_size(); -#ifdef _LP64 - int size = header_size + align_object_offset(vtable_len); -#else int size = header_size + vtable_len; -#endif return align_object_size(size); } diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 4c8986bdcec..f96838b4b5b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2910,12 +2910,9 @@ void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { Klass::collect_statistics(sz); sz->_inst_size = HeapWordSize * size_helper(); - sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length()); - sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length()); - sz->_nonstatic_oopmap_bytes = HeapWordSize * - ((is_interface() || is_anonymous()) ? - align_object_offset(nonstatic_oop_map_size()) : - nonstatic_oop_map_size()); + sz->_vtab_bytes = HeapWordSize * vtable_length(); + sz->_itab_bytes = HeapWordSize * itable_length(); + sz->_nonstatic_oopmap_bytes = HeapWordSize * nonstatic_oop_map_size(); int n = 0; n += (sz->_methods_array_bytes = sz->count_array(methods())); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 344ceb74eb8..35eb8ed0486 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -927,17 +927,15 @@ public: } // Sizing (in words) - static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); } + static int header_size() { return sizeof(InstanceKlass)/HeapWordSize; } static int size(int vtable_length, int itable_length, int nonstatic_oop_map_size, bool is_interface, bool is_anonymous) { return align_object_size(header_size() + - align_object_offset(vtable_length) + - align_object_offset(itable_length) + - ((is_interface || is_anonymous) ? - align_object_offset(nonstatic_oop_map_size) : - nonstatic_oop_map_size) + + vtable_length + + itable_length + + nonstatic_oop_map_size + (is_interface ? (int)sizeof(Klass*)/HeapWordSize : 0) + (is_anonymous ? (int)sizeof(Klass*)/HeapWordSize : 0)); } @@ -955,7 +953,7 @@ public: static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } intptr_t* start_of_vtable() const { return ((intptr_t*)this) + vtable_start_offset(); } - intptr_t* start_of_itable() const { return start_of_vtable() + align_object_offset(vtable_length()); } + intptr_t* start_of_itable() const { return start_of_vtable() + vtable_length(); } int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; } intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); } @@ -963,7 +961,7 @@ public: address static_field_addr(int offset); OopMapBlock* start_of_nonstatic_oop_maps() const { - return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length())); + return (OopMapBlock*)(start_of_itable() + itable_length()); } Klass** end_of_nonstatic_oop_maps() const { From 6ee07f50c8967379e98e1a76d37f2cf961c88c48 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 21 Jan 2016 12:11:20 -0500 Subject: [PATCH 004/139] 8146435: [TESTBUG] Logging tests are failing intermittently on windows when executed by JPRT Improved robustness of UL tests by removing reliance on "java -version" and replacing with explicit code to trigger logging in all environments Reviewed-by: dholmes, iklam, mockner --- hotspot/test/runtime/logging/ClassB.java | 2 +- .../logging/ClassInitializationTest.java | 30 +++++++++---- .../runtime/logging/ClassResolutionTest.java | 18 ++++---- .../runtime/logging/DefaultMethodsTest.java | 13 ++++-- .../test/runtime/logging/ExceptionsTest.java | 32 +++++++------- hotspot/test/runtime/logging/ItablesTest.java | 13 +++--- .../runtime/logging/ItablesVtableTest.java | 42 +++++++++++++++++++ .../runtime/logging/MonitorInflationTest.java | 18 ++++---- .../test/runtime/logging/SafepointTest.java | 6 +-- .../test/runtime/logging/VMOperationTest.java | 9 ++-- hotspot/test/runtime/logging/VtablesTest.java | 5 +-- 11 files changed, 128 insertions(+), 60 deletions(-) create mode 100644 hotspot/test/runtime/logging/ItablesVtableTest.java diff --git a/hotspot/test/runtime/logging/ClassB.java b/hotspot/test/runtime/logging/ClassB.java index 0642e13c572..c6cb4a613e9 100644 --- a/hotspot/test/runtime/logging/ClassB.java +++ b/hotspot/test/runtime/logging/ClassB.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/hotspot/test/runtime/logging/ClassInitializationTest.java b/hotspot/test/runtime/logging/ClassInitializationTest.java index eb0583d4386..3a5c4e3f9ba 100644 --- a/hotspot/test/runtime/logging/ClassInitializationTest.java +++ b/hotspot/test/runtime/logging/ClassInitializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,10 @@ public class ClassInitializationTest { public static void main(String... args) throws Exception { // (1) - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=info", "-Xverify:all", "-Xmx64m", "BadMap50"); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=info", + "-Xverify:all", + "-Xmx64m", + "BadMap50"); OutputAnalyzer out = new OutputAnalyzer(pb.start()); out.shouldContain("Start class verification for:"); out.shouldContain("End class verification for:"); @@ -50,16 +53,29 @@ public class ClassInitializationTest { // (2) if (Platform.isDebugBuild()) { - pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=info", "-Xverify:all", "-XX:+EagerInitialization", "-Xmx64m", "-version"); - out = new OutputAnalyzer(pb.start()); - out.shouldContain("[Initialized").shouldContain("without side effects]"); - out.shouldHaveExitValue(0); + pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=info", + "-Xverify:all", + "-XX:+EagerInitialization", + "-Xmx64m", + InnerClass.class.getName()); + out = new OutputAnalyzer(pb.start()); + out.shouldContain("[Initialized").shouldContain("without side effects]"); + out.shouldHaveExitValue(0); } // (3) Ensure that VerboseVerification still triggers appropriate messages. - pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions", "-XX:+VerboseVerification", "-Xverify:all", "-Xmx64m", "BadMap50"); + pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions", + "-XX:+VerboseVerification", + "-Xverify:all", + "-Xmx64m", + "BadMap50"); out = new OutputAnalyzer(pb.start()); out.shouldContain("End class verification for:"); out.shouldContain("Verification for BadMap50 failed"); out.shouldContain("Fail over class verification to old verifier for: BadMap50"); } + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Inner Class"); + } + } } diff --git a/hotspot/test/runtime/logging/ClassResolutionTest.java b/hotspot/test/runtime/logging/ClassResolutionTest.java index 84d06c4eebb..2a98f5ac68c 100644 --- a/hotspot/test/runtime/logging/ClassResolutionTest.java +++ b/hotspot/test/runtime/logging/ClassResolutionTest.java @@ -58,26 +58,28 @@ public class ClassResolutionTest { public static void main(String... args) throws Exception { // (1) classresolve should turn on. - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:classresolve=info", ClassResolutionTestMain.class.getName()); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=info", + ClassResolutionTestMain.class.getName()); OutputAnalyzer o = new OutputAnalyzer(pb.start()); o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); // (2) classresolve should turn off. - pb = ProcessTools.createJavaProcessBuilder( - "-Xlog", "-Xlog:classresolve=off", ClassResolutionTestMain.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-Xlog", + "-Xlog:classresolve=off", + ClassResolutionTestMain.class.getName()); o = new OutputAnalyzer(pb.start()); o.shouldNotContain("[classresolve]"); // (3) TraceClassResolution should turn on. - pb = ProcessTools.createJavaProcessBuilder( - "-XX:+TraceClassResolution", ClassResolutionTestMain.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceClassResolution", + ClassResolutionTestMain.class.getName()); o = new OutputAnalyzer(pb.start()); o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); // (4) TraceClassResolution should turn off. - pb = ProcessTools.createJavaProcessBuilder( - "-Xlog", "-XX:-TraceClassResolution", ClassResolutionTestMain.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-Xlog", + "-XX:-TraceClassResolution", + ClassResolutionTestMain.class.getName()); o = new OutputAnalyzer(pb.start()); o.shouldNotContain("[classresolve]"); diff --git a/hotspot/test/runtime/logging/DefaultMethodsTest.java b/hotspot/test/runtime/logging/DefaultMethodsTest.java index 9e08ba72a35..c1ac868906e 100644 --- a/hotspot/test/runtime/logging/DefaultMethodsTest.java +++ b/hotspot/test/runtime/logging/DefaultMethodsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * 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 @@ * @bug 8139564 * @summary defaultmethods=debug should have logging from each of the statements in the code * @library /testlibrary - * @ignore 8146435 * @modules java.base/sun.misc * java.management * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools @@ -38,8 +37,8 @@ import jdk.test.lib.ProcessTools; public class DefaultMethodsTest { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:defaultmethods=debug", "-version"); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:defaultmethods=debug", + InnerClass.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Slots that need filling:"); output.shouldContain("requires default method processing"); @@ -51,5 +50,11 @@ public class DefaultMethodsTest { output.shouldContain("default methods"); output.shouldHaveExitValue(0); } + + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Inner Class"); + } + } } diff --git a/hotspot/test/runtime/logging/ExceptionsTest.java b/hotspot/test/runtime/logging/ExceptionsTest.java index bac3dd0cdb0..b3c637ad251 100644 --- a/hotspot/test/runtime/logging/ExceptionsTest.java +++ b/hotspot/test/runtime/logging/ExceptionsTest.java @@ -52,28 +52,28 @@ public class ExceptionsTest { } public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:exceptions=info", "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", - InternalClass.class.getName()); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:exceptions=info", + "-Xcomp", + "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", + InternalClass.class.getName()); analyzeOutputOn(pb); - pb = ProcessTools.createJavaProcessBuilder( - "-XX:+TraceExceptions", "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", - InternalClass.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceExceptions", + "-Xcomp", + "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", + InternalClass.class.getName()); analyzeOutputOn(pb); - pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:exceptions=off", "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", - InternalClass.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-Xlog:exceptions=off", + "-Xcomp", + "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", + InternalClass.class.getName()); analyzeOutputOff(pb); - pb = ProcessTools.createJavaProcessBuilder( - "-XX:-TraceExceptions", "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", - InternalClass.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceExceptions", + "-Xcomp", + "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", + InternalClass.class.getName()); analyzeOutputOff(pb); } diff --git a/hotspot/test/runtime/logging/ItablesTest.java b/hotspot/test/runtime/logging/ItablesTest.java index 4cad4392bad..c1cfd33d865 100644 --- a/hotspot/test/runtime/logging/ItablesTest.java +++ b/hotspot/test/runtime/logging/ItablesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,8 @@ * @summary itables=trace should have logging from each of the statements * in the code * @library /testlibrary - * @ignore 8146435 * @compile ClassB.java + * ItablesVtableTest.java * @modules java.base/sun.misc * java.management * @run driver ItablesTest @@ -39,12 +39,10 @@ import jdk.test.lib.*; public class ItablesTest { public static void main(String[] args) throws Exception { if (Platform.isDebugBuild()) { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:itables=trace", "ClassB"); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:itables=trace", "ClassB"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain(": Initializing itables for ClassB"); output.shouldContain(": Initializing itable indices for interface "); - output.shouldContain("vtable index "); output.shouldContain("itable index "); output.shouldContain("target: ClassB.Method1()V, method_holder: ClassB target_method flags: public"); output.shouldContain("invokeinterface resolved method: caller-class"); @@ -53,6 +51,11 @@ public class ItablesTest { output.shouldContain("invokeinterface selected method: receiver-class"); output.shouldContain("Resolving: klass: "); output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:itables=trace", "ItablesVtableTest"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("vtable index "); + output.shouldHaveExitValue(0); } } } diff --git a/hotspot/test/runtime/logging/ItablesVtableTest.java b/hotspot/test/runtime/logging/ItablesVtableTest.java new file mode 100644 index 00000000000..fb07a9be545 --- /dev/null +++ b/hotspot/test/runtime/logging/ItablesVtableTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +interface Interface1 { + public void foo(); + public int hashCode(); +} + +public class ItablesVtableTest implements Interface1 { + public void foo() { + System.out.println("ItablesVtableTest foo"); + } + public int hashCode() { + return 55; + } + + public static void main(String[] unused) { + ItablesVtableTest c = new ItablesVtableTest(); + c.foo(); + System.out.println("Interface1 hashCode " + c.hashCode()); + } +} diff --git a/hotspot/test/runtime/logging/MonitorInflationTest.java b/hotspot/test/runtime/logging/MonitorInflationTest.java index 7399ea6dce9..781ee83c6cd 100644 --- a/hotspot/test/runtime/logging/MonitorInflationTest.java +++ b/hotspot/test/runtime/logging/MonitorInflationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,20 +51,20 @@ public class MonitorInflationTest { } public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:monitorinflation=debug", InnerClass.class.getName()); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:monitorinflation=debug", + InnerClass.class.getName()); analyzeOutputOn(pb); - pb = ProcessTools.createJavaProcessBuilder( - "-XX:+TraceMonitorInflation", InnerClass.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceMonitorInflation", + InnerClass.class.getName()); analyzeOutputOn(pb); - pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:monitorinflation=off", InnerClass.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-Xlog:monitorinflation=off", + InnerClass.class.getName()); analyzeOutputOff(pb); - pb = ProcessTools.createJavaProcessBuilder( - "-XX:-TraceMonitorInflation", InnerClass.class.getName()); + pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceMonitorInflation", + InnerClass.class.getName()); analyzeOutputOff(pb); } diff --git a/hotspot/test/runtime/logging/SafepointTest.java b/hotspot/test/runtime/logging/SafepointTest.java index 100edfad9e9..a57eaa811a5 100644 --- a/hotspot/test/runtime/logging/SafepointTest.java +++ b/hotspot/test/runtime/logging/SafepointTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,8 @@ import jdk.test.lib.ProcessTools; public class SafepointTest { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:safepoint=trace", InnerClass.class.getName()); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:safepoint=trace", + InnerClass.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Safepoint synchronization initiated. ("); output.shouldContain("Entering safepoint region: "); diff --git a/hotspot/test/runtime/logging/VMOperationTest.java b/hotspot/test/runtime/logging/VMOperationTest.java index 8b8c9c3e210..13570d6af6d 100644 --- a/hotspot/test/runtime/logging/VMOperationTest.java +++ b/hotspot/test/runtime/logging/VMOperationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,9 +38,10 @@ import jdk.test.lib.ProcessTools; public class VMOperationTest { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:vmoperation=debug", "-Xmx64m", "-Xms64m", - InternalClass.class.getName()); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:vmoperation=debug", + "-Xmx64m", + "-Xms64m", + InternalClass.class.getName()); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("VM_Operation ("); output.shouldHaveExitValue(0); diff --git a/hotspot/test/runtime/logging/VtablesTest.java b/hotspot/test/runtime/logging/VtablesTest.java index e31d4cde2fc..9df4c595069 100644 --- a/hotspot/test/runtime/logging/VtablesTest.java +++ b/hotspot/test/runtime/logging/VtablesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,7 @@ import jdk.test.lib.*; public class VtablesTest { public static void main(String[] args) throws Exception { if (Platform.isDebugBuild()) { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-Xlog:vtables=trace", "ClassB"); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:vtables=trace", "ClassB"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("copy vtable from ClassA to ClassB"); output.shouldContain("Initializing: ClassB"); From a42a7f237699ea257e72a357a72a1adf08dc28bd Mon Sep 17 00:00:00 2001 From: Derek White Date: Fri, 22 Jan 2016 06:13:52 -0500 Subject: [PATCH 005/139] 8141421: Various test fail with OOME on win x86 Fix memory overuse in g1CodeCacheRemset Reviewed-by: tschatzl, mgerdin --- .../src/share/vm/gc/g1/g1CodeCacheRemSet.cpp | 23 ++++++++++++------- .../src/share/vm/gc/g1/heapRegionRemSet.cpp | 11 ++++++++- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp index 4180191ea0d..afbe72c8c6a 100644 --- a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,10 +74,16 @@ class CodeRootSetTable : public Hashtable { static size_t static_mem_size() { return sizeof(_purge_list); } + + size_t mem_size(); }; CodeRootSetTable* volatile CodeRootSetTable::_purge_list = NULL; +size_t CodeRootSetTable::mem_size() { + return sizeof(CodeRootSetTable) + (entry_size() * number_of_entries()) + (sizeof(HashtableBucket) * table_size()); +} + CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) { unsigned int hash = compute_hash(nm); Entry* entry = (Entry*) new_entry_free_list(); @@ -232,7 +238,6 @@ void G1CodeRootSet::move_to_large() { OrderAccess::release_store_ptr(&_table, temp); } - void G1CodeRootSet::purge() { CodeRootSetTable::purge(); } @@ -247,12 +252,13 @@ void G1CodeRootSet::add(nmethod* method) { allocate_small_table(); } added = _table->add(method); - if (_length == Threshold) { - move_to_large(); - } if (added) { + if (_length == Threshold) { + move_to_large(); + } ++_length; } + assert(_length == (size_t)_table->number_of_entries(), "sizes should match"); } bool G1CodeRootSet::remove(nmethod* method) { @@ -266,11 +272,13 @@ bool G1CodeRootSet::remove(nmethod* method) { clear(); } } + assert((_length == 0 && _table == NULL) || + (_length == (size_t)_table->number_of_entries()), "sizes should match"); return removed; } bool G1CodeRootSet::contains(nmethod* method) { - CodeRootSetTable* table = load_acquire_table(); + CodeRootSetTable* table = load_acquire_table(); // contains() may be called outside of lock, so ensure mem sync. if (table != NULL) { return table->contains(method); } @@ -284,8 +292,7 @@ void G1CodeRootSet::clear() { } size_t G1CodeRootSet::mem_size() { - return sizeof(*this) + - (_table != NULL ? sizeof(CodeRootSetTable) + _table->entry_size() * _length : 0); + return sizeof(*this) + (_table != NULL ? _table->mem_size() : 0); } void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const { diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 30fed52f93c..2ed34adae19 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -785,6 +785,9 @@ void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs, void HeapRegionRemSet::add_strong_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); + assert((!CodeCache_lock->owned_by_self() || SafepointSynchronize::is_at_safepoint()), + "should call add_strong_code_root_locked instead. CodeCache_lock->owned_by_self(): %s, is_at_safepoint(): %s", + BOOL_TO_STR(CodeCache_lock->owned_by_self()), BOOL_TO_STR(SafepointSynchronize::is_at_safepoint())); // Optimistic unlocked contains-check if (!_code_roots.contains(nm)) { MutexLockerEx ml(&_m, Mutex::_no_safepoint_check_flag); @@ -794,6 +797,12 @@ void HeapRegionRemSet::add_strong_code_root(nmethod* nm) { void HeapRegionRemSet::add_strong_code_root_locked(nmethod* nm) { assert(nm != NULL, "sanity"); + assert((CodeCache_lock->owned_by_self() || + (SafepointSynchronize::is_at_safepoint() && + (_m.owned_by_self() || Thread::current()->is_VM_thread()))), + "not safely locked. CodeCache_lock->owned_by_self(): %s, is_at_safepoint(): %s, _m.owned_by_self(): %s, Thread::current()->is_VM_thread(): %s", + BOOL_TO_STR(CodeCache_lock->owned_by_self()), BOOL_TO_STR(SafepointSynchronize::is_at_safepoint()), + BOOL_TO_STR(_m.owned_by_self()), BOOL_TO_STR(Thread::current()->is_VM_thread())); _code_roots.add(nm); } From ac117697a31e1a5e10e7d3bede835d1004069be8 Mon Sep 17 00:00:00 2001 From: David Lindholm Date: Tue, 26 Jan 2016 15:28:31 +0100 Subject: [PATCH 006/139] 8147814: Move verification code out of g1collectedheap Reviewed-by: jwilhelm, tschatzl --- hotspot/src/share/vm/gc/g1/concurrentMark.cpp | 13 +- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 778 +----------------- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 66 +- hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp | 3 +- hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp | 731 ++++++++++++++++ hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp | 115 +++ 6 files changed, 893 insertions(+), 813 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp create mode 100644 hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp index 7c805879930..a7c70b9483e 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp @@ -31,6 +31,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/heapRegion.inline.hpp" @@ -1062,7 +1063,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { g1h->prepare_for_verify(); Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (before)"); } - g1h->check_bitmaps("Remark Start"); + g1h->verifier()->check_bitmaps("Remark Start"); G1CollectorPolicy* g1p = g1h->g1_policy(); g1p->record_concurrent_mark_remark_start(); @@ -1111,7 +1112,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { g1h->prepare_for_verify(); Universe::verify(VerifyOption_G1UseNextMarking, "During GC (after)"); } - g1h->check_bitmaps("Remark End"); + g1h->verifier()->check_bitmaps("Remark End"); assert(!restart_for_overflow(), "sanity"); // Completely reset the marking state since marking completed set_non_marking_state(); @@ -1605,14 +1606,14 @@ void ConcurrentMark::cleanup() { return; } - g1h->verify_region_sets_optional(); + g1h->verifier()->verify_region_sets_optional(); if (VerifyDuringGC) { HandleMark hm; // handle scope g1h->prepare_for_verify(); Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (before)"); } - g1h->check_bitmaps("Cleanup Start"); + g1h->verifier()->check_bitmaps("Cleanup Start"); G1CollectorPolicy* g1p = g1h->g1_policy(); g1p->record_concurrent_mark_cleanup_start(); @@ -1702,9 +1703,9 @@ void ConcurrentMark::cleanup() { Universe::verify(VerifyOption_G1UsePrevMarking, "During GC (after)"); } - g1h->check_bitmaps("Cleanup End"); + g1h->verifier()->check_bitmaps("Cleanup End"); - g1h->verify_region_sets_optional(); + g1h->verifier()->verify_region_sets_optional(); // We need to make this be a "collection" so any collection pause that // races with it goes around and waits for completeCleanup to finish. diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index e2ecfaa24f5..accba8f5bd7 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -38,6 +38,7 @@ #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" +#include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1MarkSweep.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" @@ -399,7 +400,7 @@ G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, assert(hr->bottom() < obj_top && obj_top <= hr->end(), "obj_top should be in last region"); - check_bitmaps("Humongous Region Allocation", first_hr); + _verifier->check_bitmaps("Humongous Region Allocation", first_hr); assert(words_not_fillable == 0 || first_hr->bottom() + word_size_sum - words_not_fillable == hr->top(), @@ -427,7 +428,7 @@ size_t G1CollectedHeap::humongous_obj_size_in_regions(size_t word_size) { HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size, AllocationContext_t context) { assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); uint first = G1_NO_HRM_INDEX; uint obj_regions = (uint) humongous_obj_size_in_regions(word_size); @@ -501,7 +502,7 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size, AllocationCo g1mm()->update_sizes(); } - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); return result; } @@ -1230,7 +1231,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, size_t metadata_prev_used = MetaspaceAux::used_bytes(); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); const bool do_clear_all_soft_refs = clear_all_soft_refs || collector_policy()->should_clear_all_soft_refs(); @@ -1271,9 +1272,9 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, assert(used() == recalculate_used(), "Should be equal"); - verify_before_gc(); + _verifier->verify_before_gc(); - check_bitmaps("Full GC Start"); + _verifier->check_bitmaps("Full GC Start"); pre_full_gc_dump(gc_timer); #if defined(COMPILER2) || INCLUDE_JVMCI @@ -1408,9 +1409,9 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, increment_old_marking_cycles_completed(false /* concurrent */); _hrm.verify_optional(); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); - verify_after_gc(); + _verifier->verify_after_gc(); // Clear the previous marking bitmap, if needed for bitmap verification. // Note we cannot do this when we clear the next marking bitmap in @@ -1422,7 +1423,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, if (G1VerifyBitmaps) { ((CMBitMap*) concurrent_mark()->prevMarkBitMap())->clearAll(); } - check_bitmaps("Full GC End"); + _verifier->check_bitmaps("Full GC End"); // Start a new incremental collection set for the next pause assert(g1_policy()->collection_set() == NULL, "must be"); @@ -1639,7 +1640,7 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size, HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size, AllocationContext_t context) { assert_at_safepoint(true /* should_be_vm_thread */); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); size_t expand_bytes = MAX2(word_size * HeapWordSize, MinHeapDeltaBytes); log_debug(gc, ergo, heap)("Attempt heap expansion (allocation request failed). Allocation request: " SIZE_FORMAT "B", @@ -1648,7 +1649,7 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size, AllocationConte if (expand(expand_bytes)) { _hrm.verify_optional(); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); return attempt_allocation_at_safepoint(word_size, context, false /* expect_null_mutator_alloc_region */); @@ -1717,7 +1718,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { } void G1CollectedHeap::shrink(size_t shrink_bytes) { - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); // We should only reach here at the end of a Full GC which means we // should not not be holding to any GC alloc regions. The method @@ -1732,7 +1733,7 @@ void G1CollectedHeap::shrink(size_t shrink_bytes) { rebuild_region_sets(true /* free_list_only */); _hrm.verify_optional(); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); } // Public methods. @@ -1778,6 +1779,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : /* are_GC_task_threads */true, /* are_ConcurrentGC_threads */false); _workers->initialize_workers(); + _verifier = new G1HeapVerifier(this); _allocator = G1Allocator::create_allocator(this); _humongous_object_threshold_in_words = humongous_threshold_for(HeapRegion::GrainWords); @@ -2667,452 +2669,11 @@ jlong G1CollectedHeap::millis_since_last_gc() { } void G1CollectedHeap::prepare_for_verify() { - if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { - ensure_parsability(false); - } - g1_rem_set()->prepare_for_verify(); + _verifier->prepare_for_verify(); } -bool G1CollectedHeap::allocated_since_marking(oop obj, HeapRegion* hr, - VerifyOption vo) { - switch (vo) { - case VerifyOption_G1UsePrevMarking: - return hr->obj_allocated_since_prev_marking(obj); - case VerifyOption_G1UseNextMarking: - return hr->obj_allocated_since_next_marking(obj); - case VerifyOption_G1UseMarkWord: - return false; - default: - ShouldNotReachHere(); - } - return false; // keep some compilers happy -} - -HeapWord* G1CollectedHeap::top_at_mark_start(HeapRegion* hr, VerifyOption vo) { - switch (vo) { - case VerifyOption_G1UsePrevMarking: return hr->prev_top_at_mark_start(); - case VerifyOption_G1UseNextMarking: return hr->next_top_at_mark_start(); - case VerifyOption_G1UseMarkWord: return NULL; - default: ShouldNotReachHere(); - } - return NULL; // keep some compilers happy -} - -bool G1CollectedHeap::is_marked(oop obj, VerifyOption vo) { - switch (vo) { - case VerifyOption_G1UsePrevMarking: return isMarkedPrev(obj); - case VerifyOption_G1UseNextMarking: return isMarkedNext(obj); - case VerifyOption_G1UseMarkWord: return obj->is_gc_marked(); - default: ShouldNotReachHere(); - } - return false; // keep some compilers happy -} - -const char* G1CollectedHeap::top_at_mark_start_str(VerifyOption vo) { - switch (vo) { - case VerifyOption_G1UsePrevMarking: return "PTAMS"; - case VerifyOption_G1UseNextMarking: return "NTAMS"; - case VerifyOption_G1UseMarkWord: return "NONE"; - default: ShouldNotReachHere(); - } - return NULL; // keep some compilers happy -} - -class VerifyRootsClosure: public OopClosure { -private: - G1CollectedHeap* _g1h; - VerifyOption _vo; - bool _failures; -public: - // _vo == UsePrevMarking -> use "prev" marking information, - // _vo == UseNextMarking -> use "next" marking information, - // _vo == UseMarkWord -> use mark word from object header. - VerifyRootsClosure(VerifyOption vo) : - _g1h(G1CollectedHeap::heap()), - _vo(vo), - _failures(false) { } - - bool failures() { return _failures; } - - template void do_oop_nv(T* p) { - T heap_oop = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(heap_oop)) { - oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if (_g1h->is_obj_dead_cond(obj, _vo)) { - LogHandle(gc, verify) log; - log.info("Root location " PTR_FORMAT " points to dead obj " PTR_FORMAT, p2i(p), p2i(obj)); - if (_vo == VerifyOption_G1UseMarkWord) { - log.info(" Mark word: " PTR_FORMAT, p2i(obj->mark())); - } - ResourceMark rm; - obj->print_on(log.info_stream()); - _failures = true; - } - } - } - - void do_oop(oop* p) { do_oop_nv(p); } - void do_oop(narrowOop* p) { do_oop_nv(p); } -}; - -class G1VerifyCodeRootOopClosure: public OopClosure { - G1CollectedHeap* _g1h; - OopClosure* _root_cl; - nmethod* _nm; - VerifyOption _vo; - bool _failures; - - template void do_oop_work(T* p) { - // First verify that this root is live - _root_cl->do_oop(p); - - if (!G1VerifyHeapRegionCodeRoots) { - // We're not verifying the code roots attached to heap region. - return; - } - - // Don't check the code roots during marking verification in a full GC - if (_vo == VerifyOption_G1UseMarkWord) { - return; - } - - // Now verify that the current nmethod (which contains p) is - // in the code root list of the heap region containing the - // object referenced by p. - - T heap_oop = oopDesc::load_heap_oop(p); - if (!oopDesc::is_null(heap_oop)) { - oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - - // Now fetch the region containing the object - HeapRegion* hr = _g1h->heap_region_containing(obj); - HeapRegionRemSet* hrrs = hr->rem_set(); - // Verify that the strong code root list for this region - // contains the nmethod - if (!hrrs->strong_code_roots_list_contains(_nm)) { - log_info(gc, verify)("Code root location " PTR_FORMAT " " - "from nmethod " PTR_FORMAT " not in strong " - "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")", - p2i(p), p2i(_nm), p2i(hr->bottom()), p2i(hr->end())); - _failures = true; - } - } - } - -public: - G1VerifyCodeRootOopClosure(G1CollectedHeap* g1h, OopClosure* root_cl, VerifyOption vo): - _g1h(g1h), _root_cl(root_cl), _vo(vo), _nm(NULL), _failures(false) {} - - void do_oop(oop* p) { do_oop_work(p); } - void do_oop(narrowOop* p) { do_oop_work(p); } - - void set_nmethod(nmethod* nm) { _nm = nm; } - bool failures() { return _failures; } -}; - -class G1VerifyCodeRootBlobClosure: public CodeBlobClosure { - G1VerifyCodeRootOopClosure* _oop_cl; - -public: - G1VerifyCodeRootBlobClosure(G1VerifyCodeRootOopClosure* oop_cl): - _oop_cl(oop_cl) {} - - void do_code_blob(CodeBlob* cb) { - nmethod* nm = cb->as_nmethod_or_null(); - if (nm != NULL) { - _oop_cl->set_nmethod(nm); - nm->oops_do(_oop_cl); - } - } -}; - -class YoungRefCounterClosure : public OopClosure { - G1CollectedHeap* _g1h; - int _count; - public: - YoungRefCounterClosure(G1CollectedHeap* g1h) : _g1h(g1h), _count(0) {} - void do_oop(oop* p) { if (_g1h->is_in_young(*p)) { _count++; } } - void do_oop(narrowOop* p) { ShouldNotReachHere(); } - - int count() { return _count; } - void reset_count() { _count = 0; }; -}; - -class VerifyKlassClosure: public KlassClosure { - YoungRefCounterClosure _young_ref_counter_closure; - OopClosure *_oop_closure; - public: - VerifyKlassClosure(G1CollectedHeap* g1h, OopClosure* cl) : _young_ref_counter_closure(g1h), _oop_closure(cl) {} - void do_klass(Klass* k) { - k->oops_do(_oop_closure); - - _young_ref_counter_closure.reset_count(); - k->oops_do(&_young_ref_counter_closure); - if (_young_ref_counter_closure.count() > 0) { - guarantee(k->has_modified_oops(), "Klass " PTR_FORMAT ", has young refs but is not dirty.", p2i(k)); - } - } -}; - -class VerifyLivenessOopClosure: public OopClosure { - G1CollectedHeap* _g1h; - VerifyOption _vo; -public: - VerifyLivenessOopClosure(G1CollectedHeap* g1h, VerifyOption vo): - _g1h(g1h), _vo(vo) - { } - void do_oop(narrowOop *p) { do_oop_work(p); } - void do_oop( oop *p) { do_oop_work(p); } - - template void do_oop_work(T *p) { - oop obj = oopDesc::load_decode_heap_oop(p); - guarantee(obj == NULL || !_g1h->is_obj_dead_cond(obj, _vo), - "Dead object referenced by a not dead object"); - } -}; - -class VerifyObjsInRegionClosure: public ObjectClosure { -private: - G1CollectedHeap* _g1h; - size_t _live_bytes; - HeapRegion *_hr; - VerifyOption _vo; -public: - // _vo == UsePrevMarking -> use "prev" marking information, - // _vo == UseNextMarking -> use "next" marking information, - // _vo == UseMarkWord -> use mark word from object header. - VerifyObjsInRegionClosure(HeapRegion *hr, VerifyOption vo) - : _live_bytes(0), _hr(hr), _vo(vo) { - _g1h = G1CollectedHeap::heap(); - } - void do_object(oop o) { - VerifyLivenessOopClosure isLive(_g1h, _vo); - assert(o != NULL, "Huh?"); - if (!_g1h->is_obj_dead_cond(o, _vo)) { - // If the object is alive according to the mark word, - // then verify that the marking information agrees. - // Note we can't verify the contra-positive of the - // above: if the object is dead (according to the mark - // word), it may not be marked, or may have been marked - // but has since became dead, or may have been allocated - // since the last marking. - if (_vo == VerifyOption_G1UseMarkWord) { - guarantee(!_g1h->is_obj_dead(o), "mark word and concurrent mark mismatch"); - } - - o->oop_iterate_no_header(&isLive); - if (!_hr->obj_allocated_since_prev_marking(o)) { - size_t obj_size = o->size(); // Make sure we don't overflow - _live_bytes += (obj_size * HeapWordSize); - } - } - } - size_t live_bytes() { return _live_bytes; } -}; - -class VerifyArchiveOopClosure: public OopClosure { -public: - VerifyArchiveOopClosure(HeapRegion *hr) { } - void do_oop(narrowOop *p) { do_oop_work(p); } - void do_oop( oop *p) { do_oop_work(p); } - - template void do_oop_work(T *p) { - oop obj = oopDesc::load_decode_heap_oop(p); - guarantee(obj == NULL || G1MarkSweep::in_archive_range(obj), - "Archive object at " PTR_FORMAT " references a non-archive object at " PTR_FORMAT, - p2i(p), p2i(obj)); - } -}; - -class VerifyArchiveRegionClosure: public ObjectClosure { -public: - VerifyArchiveRegionClosure(HeapRegion *hr) { } - // Verify that all object pointers are to archive regions. - void do_object(oop o) { - VerifyArchiveOopClosure checkOop(NULL); - assert(o != NULL, "Should not be here for NULL oops"); - o->oop_iterate_no_header(&checkOop); - } -}; - -class VerifyRegionClosure: public HeapRegionClosure { -private: - bool _par; - VerifyOption _vo; - bool _failures; -public: - // _vo == UsePrevMarking -> use "prev" marking information, - // _vo == UseNextMarking -> use "next" marking information, - // _vo == UseMarkWord -> use mark word from object header. - VerifyRegionClosure(bool par, VerifyOption vo) - : _par(par), - _vo(vo), - _failures(false) {} - - bool failures() { - return _failures; - } - - bool doHeapRegion(HeapRegion* r) { - // For archive regions, verify there are no heap pointers to - // non-pinned regions. For all others, verify liveness info. - if (r->is_archive()) { - VerifyArchiveRegionClosure verify_oop_pointers(r); - r->object_iterate(&verify_oop_pointers); - return true; - } - if (!r->is_continues_humongous()) { - bool failures = false; - r->verify(_vo, &failures); - if (failures) { - _failures = true; - } else if (!r->is_starts_humongous()) { - VerifyObjsInRegionClosure not_dead_yet_cl(r, _vo); - r->object_iterate(¬_dead_yet_cl); - if (_vo != VerifyOption_G1UseNextMarking) { - if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) { - log_info(gc, verify)("[" PTR_FORMAT "," PTR_FORMAT "] max_live_bytes " SIZE_FORMAT " < calculated " SIZE_FORMAT, - p2i(r->bottom()), p2i(r->end()), r->max_live_bytes(), not_dead_yet_cl.live_bytes()); - _failures = true; - } - } else { - // When vo == UseNextMarking we cannot currently do a sanity - // check on the live bytes as the calculation has not been - // finalized yet. - } - } - } - return false; // stop the region iteration if we hit a failure - } -}; - -// This is the task used for parallel verification of the heap regions - -class G1ParVerifyTask: public AbstractGangTask { -private: - G1CollectedHeap* _g1h; - VerifyOption _vo; - bool _failures; - HeapRegionClaimer _hrclaimer; - -public: - // _vo == UsePrevMarking -> use "prev" marking information, - // _vo == UseNextMarking -> use "next" marking information, - // _vo == UseMarkWord -> use mark word from object header. - G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) : - AbstractGangTask("Parallel verify task"), - _g1h(g1h), - _vo(vo), - _failures(false), - _hrclaimer(g1h->workers()->active_workers()) {} - - bool failures() { - return _failures; - } - - void work(uint worker_id) { - HandleMark hm; - VerifyRegionClosure blk(true, _vo); - _g1h->heap_region_par_iterate(&blk, worker_id, &_hrclaimer); - if (blk.failures()) { - _failures = true; - } - } -}; - void G1CollectedHeap::verify(VerifyOption vo) { - if (!SafepointSynchronize::is_at_safepoint()) { - log_info(gc, verify)("Skipping verification. Not at safepoint."); - } - - assert(Thread::current()->is_VM_thread(), - "Expected to be executed serially by the VM thread at this point"); - - log_debug(gc, verify)("Roots"); - VerifyRootsClosure rootsCl(vo); - VerifyKlassClosure klassCl(this, &rootsCl); - CLDToKlassAndOopClosure cldCl(&klassCl, &rootsCl, false); - - // We apply the relevant closures to all the oops in the - // system dictionary, class loader data graph, the string table - // and the nmethods in the code cache. - G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo); - G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl); - - { - G1RootProcessor root_processor(this, 1); - root_processor.process_all_roots(&rootsCl, - &cldCl, - &blobsCl); - } - - bool failures = rootsCl.failures() || codeRootsCl.failures(); - - if (vo != VerifyOption_G1UseMarkWord) { - // If we're verifying during a full GC then the region sets - // will have been torn down at the start of the GC. Therefore - // verifying the region sets will fail. So we only verify - // the region sets when not in a full GC. - log_debug(gc, verify)("HeapRegionSets"); - verify_region_sets(); - } - - log_debug(gc, verify)("HeapRegions"); - if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { - - G1ParVerifyTask task(this, vo); - workers()->run_task(&task); - if (task.failures()) { - failures = true; - } - - } else { - VerifyRegionClosure blk(false, vo); - heap_region_iterate(&blk); - if (blk.failures()) { - failures = true; - } - } - - if (G1StringDedup::is_enabled()) { - log_debug(gc, verify)("StrDedup"); - G1StringDedup::verify(); - } - - if (failures) { - log_info(gc, verify)("Heap after failed verification:"); - // It helps to have the per-region information in the output to - // help us track down what went wrong. This is why we call - // print_extended_on() instead of print_on(). - LogHandle(gc, verify) log; - ResourceMark rm; - print_extended_on(log.info_stream()); - } - guarantee(!failures, "there should not have been any failures"); -} - -double G1CollectedHeap::verify(bool guard, const char* msg) { - double verify_time_ms = 0.0; - - if (guard && total_collections() >= VerifyGCStartAt) { - double verify_start = os::elapsedTime(); - HandleMark hm; // Discard invalid handles created during verification - prepare_for_verify(); - Universe::verify(VerifyOption_G1UsePrevMarking, msg); - verify_time_ms = (os::elapsedTime() - verify_start) * 1000; - } - - return verify_time_ms; -} - -void G1CollectedHeap::verify_before_gc() { - double verify_time_ms = verify(VerifyBeforeGC, "Before GC"); - g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms); -} - -void G1CollectedHeap::verify_after_gc() { - double verify_time_ms = verify(VerifyAfterGC, "After GC"); - g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms); + _verifier->verify(vo); } class PrintRegionClosure: public HeapRegionClosure { @@ -3657,8 +3218,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { print_heap_before_gc(); trace_heap_before_gc(_gc_tracer_stw); - verify_region_sets_optional(); - verify_dirty_young_regions(); + _verifier->verify_region_sets_optional(); + _verifier->verify_dirty_young_regions(); // This call will decide whether this pause is an initial-mark // pause. If it is, during_initial_mark_pause() will return true @@ -3741,9 +3302,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { heap_region_iterate(&v_cl); } - verify_before_gc(); + _verifier->verify_before_gc(); - check_bitmaps("GC Start"); + _verifier->check_bitmaps("GC Start"); #if defined(COMPILER2) || INCLUDE_JVMCI DerivedPointerTable::clear(); @@ -3801,7 +3362,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { register_humongous_regions_with_cset(); - assert(check_cset_fast_test(), "Inconsistency in the InCSetState table."); + assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table."); _cm->note_start_of_gc(); // We call this after finalize_cset() to @@ -3951,8 +3512,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { heap_region_iterate(&v_cl); } - verify_after_gc(); - check_bitmaps("GC End"); + _verifier->verify_after_gc(); + _verifier->check_bitmaps("GC End"); assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); ref_processor_stw()->verify_no_references_recorded(); @@ -3976,7 +3537,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { // logging output either. _hrm.verify_optional(); - verify_region_sets_optional(); + _verifier->verify_region_sets_optional(); TASKQUEUE_STATS_ONLY(print_taskqueue_stats()); TASKQUEUE_STATS_ONLY(reset_taskqueue_stats()); @@ -5245,197 +4806,6 @@ public: } }; -#ifndef PRODUCT -class G1VerifyCardTableCleanup: public HeapRegionClosure { - G1CollectedHeap* _g1h; - G1SATBCardTableModRefBS* _ct_bs; -public: - G1VerifyCardTableCleanup(G1CollectedHeap* g1h, G1SATBCardTableModRefBS* ct_bs) - : _g1h(g1h), _ct_bs(ct_bs) { } - virtual bool doHeapRegion(HeapRegion* r) { - if (r->is_survivor()) { - _g1h->verify_dirty_region(r); - } else { - _g1h->verify_not_dirty_region(r); - } - return false; - } -}; - -void G1CollectedHeap::verify_not_dirty_region(HeapRegion* hr) { - // All of the region should be clean. - G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); - MemRegion mr(hr->bottom(), hr->end()); - ct_bs->verify_not_dirty_region(mr); -} - -void G1CollectedHeap::verify_dirty_region(HeapRegion* hr) { - // We cannot guarantee that [bottom(),end()] is dirty. Threads - // dirty allocated blocks as they allocate them. The thread that - // retires each region and replaces it with a new one will do a - // maximal allocation to fill in [pre_dummy_top(),end()] but will - // not dirty that area (one less thing to have to do while holding - // a lock). So we can only verify that [bottom(),pre_dummy_top()] - // is dirty. - G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); - MemRegion mr(hr->bottom(), hr->pre_dummy_top()); - if (hr->is_young()) { - ct_bs->verify_g1_young_region(mr); - } else { - ct_bs->verify_dirty_region(mr); - } -} - -void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) { - G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); - for (HeapRegion* hr = head; hr != NULL; hr = hr->get_next_young_region()) { - verify_dirty_region(hr); - } -} - -void G1CollectedHeap::verify_dirty_young_regions() { - verify_dirty_young_list(_young_list->first_region()); -} - -bool G1CollectedHeap::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, - HeapWord* tams, HeapWord* end) { - guarantee(tams <= end, - "tams: " PTR_FORMAT " end: " PTR_FORMAT, p2i(tams), p2i(end)); - HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end); - if (result < end) { - log_info(gc, verify)("## wrong marked address on %s bitmap: " PTR_FORMAT, bitmap_name, p2i(result)); - log_info(gc, verify)("## %s tams: " PTR_FORMAT " end: " PTR_FORMAT, bitmap_name, p2i(tams), p2i(end)); - return false; - } - return true; -} - -bool G1CollectedHeap::verify_bitmaps(const char* caller, HeapRegion* hr) { - CMBitMapRO* prev_bitmap = concurrent_mark()->prevMarkBitMap(); - CMBitMapRO* next_bitmap = (CMBitMapRO*) concurrent_mark()->nextMarkBitMap(); - - HeapWord* bottom = hr->bottom(); - HeapWord* ptams = hr->prev_top_at_mark_start(); - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* end = hr->end(); - - bool res_p = verify_no_bits_over_tams("prev", prev_bitmap, ptams, end); - - bool res_n = true; - // We reset mark_in_progress() before we reset _cmThread->in_progress() and in this window - // we do the clearing of the next bitmap concurrently. Thus, we can not verify the bitmap - // if we happen to be in that state. - if (collector_state()->mark_in_progress() || !_cmThread->in_progress()) { - res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end); - } - if (!res_p || !res_n) { - log_info(gc, verify)("#### Bitmap verification failed for " HR_FORMAT, HR_FORMAT_PARAMS(hr)); - log_info(gc, verify)("#### Caller: %s", caller); - return false; - } - return true; -} - -void G1CollectedHeap::check_bitmaps(const char* caller, HeapRegion* hr) { - if (!G1VerifyBitmaps) return; - - guarantee(verify_bitmaps(caller, hr), "bitmap verification"); -} - -class G1VerifyBitmapClosure : public HeapRegionClosure { -private: - const char* _caller; - G1CollectedHeap* _g1h; - bool _failures; - -public: - G1VerifyBitmapClosure(const char* caller, G1CollectedHeap* g1h) : - _caller(caller), _g1h(g1h), _failures(false) { } - - bool failures() { return _failures; } - - virtual bool doHeapRegion(HeapRegion* hr) { - bool result = _g1h->verify_bitmaps(_caller, hr); - if (!result) { - _failures = true; - } - return false; - } -}; - -void G1CollectedHeap::check_bitmaps(const char* caller) { - if (!G1VerifyBitmaps) return; - - G1VerifyBitmapClosure cl(caller, this); - heap_region_iterate(&cl); - guarantee(!cl.failures(), "bitmap verification"); -} - -class G1CheckCSetFastTableClosure : public HeapRegionClosure { - private: - bool _failures; - public: - G1CheckCSetFastTableClosure() : HeapRegionClosure(), _failures(false) { } - - virtual bool doHeapRegion(HeapRegion* hr) { - uint i = hr->hrm_index(); - InCSetState cset_state = (InCSetState) G1CollectedHeap::heap()->_in_cset_fast_test.get_by_index(i); - if (hr->is_humongous()) { - if (hr->in_collection_set()) { - log_info(gc, verify)("## humongous region %u in CSet", i); - _failures = true; - return true; - } - if (cset_state.is_in_cset()) { - log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for humongous region %u", cset_state.value(), i); - _failures = true; - return true; - } - if (hr->is_continues_humongous() && cset_state.is_humongous()) { - log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for continues humongous region %u", cset_state.value(), i); - _failures = true; - return true; - } - } else { - if (cset_state.is_humongous()) { - log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for non-humongous region %u", cset_state.value(), i); - _failures = true; - return true; - } - if (hr->in_collection_set() != cset_state.is_in_cset()) { - log_info(gc, verify)("## in CSet %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u", - hr->in_collection_set(), cset_state.value(), i); - _failures = true; - return true; - } - if (cset_state.is_in_cset()) { - if (hr->is_young() != (cset_state.is_young())) { - log_info(gc, verify)("## is_young %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u", - hr->is_young(), cset_state.value(), i); - _failures = true; - return true; - } - if (hr->is_old() != (cset_state.is_old())) { - log_info(gc, verify)("## is_old %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u", - hr->is_old(), cset_state.value(), i); - _failures = true; - return true; - } - } - } - return false; - } - - bool failures() const { return _failures; } -}; - -bool G1CollectedHeap::check_cset_fast_test() { - G1CheckCSetFastTableClosure cl; - _hrm.iterate(&cl); - return !cl.failures(); -} -#endif // PRODUCT - class G1ParScrubRemSetTask: public AbstractGangTask { protected: G1RemSet* _g1rs; @@ -5473,10 +4843,7 @@ void G1CollectedHeap::cleanUpCardTable() { workers()->run_task(&cleanup_task); #ifndef PRODUCT - if (G1VerifyCTCleanup || VerifyAfterGC) { - G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs); - heap_region_iterate(&cleanup_verifier); - } + _verifier->verify_card_table_cleanup(); #endif } @@ -5998,7 +5365,7 @@ HeapRegion* G1CollectedHeap::new_mutator_alloc_region(size_t word_size, if (new_alloc_region != NULL) { set_region_short_lived_locked(new_alloc_region); _hr_printer.alloc(new_alloc_region, young_list_full); - check_bitmaps("Mutator Region Allocation", new_alloc_region); + _verifier->check_bitmaps("Mutator Region Allocation", new_alloc_region); return new_alloc_region; } } @@ -6038,10 +5405,10 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, new_alloc_region->record_timestamp(); if (is_survivor) { new_alloc_region->set_survivor(); - check_bitmaps("Survivor Region Allocation", new_alloc_region); + _verifier->check_bitmaps("Survivor Region Allocation", new_alloc_region); } else { new_alloc_region->set_old(); - check_bitmaps("Old Region Allocation", new_alloc_region); + _verifier->check_bitmaps("Old Region Allocation", new_alloc_region); } _hr_printer.alloc(new_alloc_region); bool during_im = collector_state()->during_initial_mark_pause(); @@ -6081,93 +5448,6 @@ HeapRegion* G1CollectedHeap::alloc_highest_free_region() { return NULL; } -// Heap region set verification - -class VerifyRegionListsClosure : public HeapRegionClosure { -private: - HeapRegionSet* _old_set; - HeapRegionSet* _humongous_set; - HeapRegionManager* _hrm; - -public: - uint _old_count; - uint _humongous_count; - uint _free_count; - - VerifyRegionListsClosure(HeapRegionSet* old_set, - HeapRegionSet* humongous_set, - HeapRegionManager* hrm) : - _old_set(old_set), _humongous_set(humongous_set), _hrm(hrm), - _old_count(), _humongous_count(), _free_count(){ } - - bool doHeapRegion(HeapRegion* hr) { - if (hr->is_young()) { - // TODO - } else if (hr->is_humongous()) { - assert(hr->containing_set() == _humongous_set, "Heap region %u is humongous but not in humongous set.", hr->hrm_index()); - _humongous_count++; - } else if (hr->is_empty()) { - assert(_hrm->is_free(hr), "Heap region %u is empty but not on the free list.", hr->hrm_index()); - _free_count++; - } else if (hr->is_old()) { - assert(hr->containing_set() == _old_set, "Heap region %u is old but not in the old set.", hr->hrm_index()); - _old_count++; - } else { - // There are no other valid region types. Check for one invalid - // one we can identify: pinned without old or humongous set. - assert(!hr->is_pinned(), "Heap region %u is pinned but not old (archive) or humongous.", hr->hrm_index()); - ShouldNotReachHere(); - } - return false; - } - - void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, HeapRegionManager* free_list) { - guarantee(old_set->length() == _old_count, "Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count); - guarantee(humongous_set->length() == _humongous_count, "Hum set count mismatch. Expected %u, actual %u.", humongous_set->length(), _humongous_count); - guarantee(free_list->num_free_regions() == _free_count, "Free list count mismatch. Expected %u, actual %u.", free_list->num_free_regions(), _free_count); - } -}; - -void G1CollectedHeap::verify_region_sets() { - assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); - - // First, check the explicit lists. - _hrm.verify(); - { - // Given that a concurrent operation might be adding regions to - // the secondary free list we have to take the lock before - // verifying it. - MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); - _secondary_free_list.verify_list(); - } - - // If a concurrent region freeing operation is in progress it will - // be difficult to correctly attributed any free regions we come - // across to the correct free list given that they might belong to - // one of several (free_list, secondary_free_list, any local lists, - // etc.). So, if that's the case we will skip the rest of the - // verification operation. Alternatively, waiting for the concurrent - // operation to complete will have a non-trivial effect on the GC's - // operation (no concurrent operation will last longer than the - // interval between two calls to verification) and it might hide - // any issues that we would like to catch during testing. - if (free_regions_coming()) { - return; - } - - // Make sure we append the secondary_free_list on the free_list so - // that all free regions we will come across can be safely - // attributed to the free_list. - append_secondary_free_list_if_not_empty_with_lock(); - - // Finally, make sure that the region accounting in the lists is - // consistent with what we see in the heap. - - VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_hrm); - heap_region_iterate(&cl); - cl.verify_counts(&_old_set, &_humongous_set, &_hrm); -} - // Optimized nmethod scanning class RegisterNMethodOopClosure: public OopClosure { diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index de5088f1f03..05cde22e58d 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -82,6 +82,7 @@ class Ticks; class WorkGang; class G1Allocator; class G1ArchiveAllocator; +class G1HeapVerifier; typedef OverflowTaskQueue RefToScanQueue; typedef GenericTaskQueueSet RefToScanQueueSet; @@ -118,6 +119,7 @@ class G1CollectedHeap : public CollectedHeap { friend class VMStructs; friend class MutatorAllocRegion; friend class G1GCAllocRegion; + friend class G1HeapVerifier; // Closures used in implementation. friend class G1ParScanThreadState; @@ -181,6 +183,9 @@ private: // Manages all allocations with regions except humongous object allocations. G1Allocator* _allocator; + // Manages all heap verification. + G1HeapVerifier* _verifier; + // Outside of GC pauses, the number of bytes used in all regions other // than the current allocation region(s). size_t _summary_bytes_used; @@ -286,10 +291,6 @@ private: size_t size, size_t translation_factor); - double verify(bool guard, const char* msg); - void verify_before_gc(); - void verify_after_gc(); - void log_gc_footer(jlong pause_time_counter); void trace_heap(GCWhen::Type when, const GCTracer* tracer); @@ -527,6 +528,10 @@ public: return _allocator; } + G1HeapVerifier* verifier() { + return _verifier; + } + G1MonitoringSupport* g1mm() { assert(_g1mm != NULL, "should have been initialized"); return _g1mm; @@ -1056,54 +1061,6 @@ public: // The number of regions that are not completely free. uint num_used_regions() const { return num_regions() - num_free_regions(); } - void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN; - void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN; - void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN; - void verify_dirty_young_regions() PRODUCT_RETURN; - -#ifndef PRODUCT - // Make sure that the given bitmap has no marked objects in the - // range [from,limit). If it does, print an error message and return - // false. Otherwise, just return true. bitmap_name should be "prev" - // or "next". - bool verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, - HeapWord* from, HeapWord* limit); - - // Verify that the prev / next bitmap range [tams,end) for the given - // region has no marks. Return true if all is well, false if errors - // are detected. - bool verify_bitmaps(const char* caller, HeapRegion* hr); -#endif // PRODUCT - - // If G1VerifyBitmaps is set, verify that the marking bitmaps for - // the given region do not have any spurious marks. If errors are - // detected, print appropriate error messages and crash. - void check_bitmaps(const char* caller, HeapRegion* hr) PRODUCT_RETURN; - - // If G1VerifyBitmaps is set, verify that the marking bitmaps do not - // have any spurious marks. If errors are detected, print - // appropriate error messages and crash. - void check_bitmaps(const char* caller) PRODUCT_RETURN; - - // Do sanity check on the contents of the in-cset fast test table. - bool check_cset_fast_test() PRODUCT_RETURN_( return true; ); - - // verify_region_sets() performs verification over the region - // lists. It will be compiled in the product code to be used when - // necessary (i.e., during heap verification). - void verify_region_sets(); - - // verify_region_sets_optional() is planted in the code for - // list verification in non-product builds (and it can be enabled in - // product builds by defining HEAP_REGION_SET_FORCE_VERIFY to be 1). -#if HEAP_REGION_SET_FORCE_VERIFY - void verify_region_sets_optional() { - verify_region_sets(); - } -#else // HEAP_REGION_SET_FORCE_VERIFY - void verify_region_sets_optional() { } -#endif // HEAP_REGION_SET_FORCE_VERIFY - #ifdef ASSERT bool is_on_master_free_list(HeapRegion* hr) { return _hrm.is_free(hr); @@ -1425,11 +1382,6 @@ public: inline bool is_obj_ill(const oop obj) const; - bool allocated_since_marking(oop obj, HeapRegion* hr, VerifyOption vo); - HeapWord* top_at_mark_start(HeapRegion* hr, VerifyOption vo); - bool is_marked(oop obj, VerifyOption vo); - const char* top_at_mark_start_str(VerifyOption vo); - ConcurrentMark* concurrent_mark() const { return _cm; } // Refinement diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp index d71a1b941c7..d34f9d7501c 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1EvacFailure.hpp" +#include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1_globals.hpp" #include "gc/g1/heapRegion.hpp" @@ -223,7 +224,7 @@ public: if (hr->evacuation_failed()) { hr->note_self_forwarding_removal_start(during_initial_mark, during_conc_mark); - _g1h->check_bitmaps("Self-Forwarding Ptr Removal", hr); + _g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr); // In the common case (i.e. when there is no evacuation // failure) we make sure that the following is done when diff --git a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp new file mode 100644 index 00000000000..ce3c8308116 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp @@ -0,0 +1,731 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#include "precompiled.hpp" +#include "logging/log.hpp" +#include "gc/g1/concurrentMarkThread.hpp" +#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1HeapVerifier.hpp" +#include "gc/g1/g1MarkSweep.hpp" +#include "gc/g1/g1RemSet.hpp" +#include "gc/g1/g1RootProcessor.hpp" +#include "gc/g1/heapRegion.hpp" +#include "gc/g1/heapRegion.inline.hpp" +#include "gc/g1/heapRegionRemSet.hpp" +#include "gc/g1/g1StringDedup.hpp" +#include "gc/g1/youngList.hpp" +#include "memory/resourceArea.hpp" +#include "oops/oop.inline.hpp" + +class VerifyRootsClosure: public OopClosure { +private: + G1CollectedHeap* _g1h; + VerifyOption _vo; + bool _failures; +public: + // _vo == UsePrevMarking -> use "prev" marking information, + // _vo == UseNextMarking -> use "next" marking information, + // _vo == UseMarkWord -> use mark word from object header. + VerifyRootsClosure(VerifyOption vo) : + _g1h(G1CollectedHeap::heap()), + _vo(vo), + _failures(false) { } + + bool failures() { return _failures; } + + template void do_oop_nv(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (_g1h->is_obj_dead_cond(obj, _vo)) { + LogHandle(gc, verify) log; + log.info("Root location " PTR_FORMAT " points to dead obj " PTR_FORMAT, p2i(p), p2i(obj)); + if (_vo == VerifyOption_G1UseMarkWord) { + log.info(" Mark word: " PTR_FORMAT, p2i(obj->mark())); + } + ResourceMark rm; + obj->print_on(log.info_stream()); + _failures = true; + } + } + } + + void do_oop(oop* p) { do_oop_nv(p); } + void do_oop(narrowOop* p) { do_oop_nv(p); } +}; + +class G1VerifyCodeRootOopClosure: public OopClosure { + G1CollectedHeap* _g1h; + OopClosure* _root_cl; + nmethod* _nm; + VerifyOption _vo; + bool _failures; + + template void do_oop_work(T* p) { + // First verify that this root is live + _root_cl->do_oop(p); + + if (!G1VerifyHeapRegionCodeRoots) { + // We're not verifying the code roots attached to heap region. + return; + } + + // Don't check the code roots during marking verification in a full GC + if (_vo == VerifyOption_G1UseMarkWord) { + return; + } + + // Now verify that the current nmethod (which contains p) is + // in the code root list of the heap region containing the + // object referenced by p. + + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + + // Now fetch the region containing the object + HeapRegion* hr = _g1h->heap_region_containing(obj); + HeapRegionRemSet* hrrs = hr->rem_set(); + // Verify that the strong code root list for this region + // contains the nmethod + if (!hrrs->strong_code_roots_list_contains(_nm)) { + log_info(gc, verify)("Code root location " PTR_FORMAT " " + "from nmethod " PTR_FORMAT " not in strong " + "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")", + p2i(p), p2i(_nm), p2i(hr->bottom()), p2i(hr->end())); + _failures = true; + } + } + } + +public: + G1VerifyCodeRootOopClosure(G1CollectedHeap* g1h, OopClosure* root_cl, VerifyOption vo): + _g1h(g1h), _root_cl(root_cl), _vo(vo), _nm(NULL), _failures(false) {} + + void do_oop(oop* p) { do_oop_work(p); } + void do_oop(narrowOop* p) { do_oop_work(p); } + + void set_nmethod(nmethod* nm) { _nm = nm; } + bool failures() { return _failures; } +}; + +class G1VerifyCodeRootBlobClosure: public CodeBlobClosure { + G1VerifyCodeRootOopClosure* _oop_cl; + +public: + G1VerifyCodeRootBlobClosure(G1VerifyCodeRootOopClosure* oop_cl): + _oop_cl(oop_cl) {} + + void do_code_blob(CodeBlob* cb) { + nmethod* nm = cb->as_nmethod_or_null(); + if (nm != NULL) { + _oop_cl->set_nmethod(nm); + nm->oops_do(_oop_cl); + } + } +}; + +class YoungRefCounterClosure : public OopClosure { + G1CollectedHeap* _g1h; + int _count; + public: + YoungRefCounterClosure(G1CollectedHeap* g1h) : _g1h(g1h), _count(0) {} + void do_oop(oop* p) { if (_g1h->is_in_young(*p)) { _count++; } } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } + + int count() { return _count; } + void reset_count() { _count = 0; }; +}; + +class VerifyKlassClosure: public KlassClosure { + YoungRefCounterClosure _young_ref_counter_closure; + OopClosure *_oop_closure; + public: + VerifyKlassClosure(G1CollectedHeap* g1h, OopClosure* cl) : _young_ref_counter_closure(g1h), _oop_closure(cl) {} + void do_klass(Klass* k) { + k->oops_do(_oop_closure); + + _young_ref_counter_closure.reset_count(); + k->oops_do(&_young_ref_counter_closure); + if (_young_ref_counter_closure.count() > 0) { + guarantee(k->has_modified_oops(), "Klass " PTR_FORMAT ", has young refs but is not dirty.", p2i(k)); + } + } +}; + +class VerifyLivenessOopClosure: public OopClosure { + G1CollectedHeap* _g1h; + VerifyOption _vo; +public: + VerifyLivenessOopClosure(G1CollectedHeap* g1h, VerifyOption vo): + _g1h(g1h), _vo(vo) + { } + void do_oop(narrowOop *p) { do_oop_work(p); } + void do_oop( oop *p) { do_oop_work(p); } + + template void do_oop_work(T *p) { + oop obj = oopDesc::load_decode_heap_oop(p); + guarantee(obj == NULL || !_g1h->is_obj_dead_cond(obj, _vo), + "Dead object referenced by a not dead object"); + } +}; + +class VerifyObjsInRegionClosure: public ObjectClosure { +private: + G1CollectedHeap* _g1h; + size_t _live_bytes; + HeapRegion *_hr; + VerifyOption _vo; +public: + // _vo == UsePrevMarking -> use "prev" marking information, + // _vo == UseNextMarking -> use "next" marking information, + // _vo == UseMarkWord -> use mark word from object header. + VerifyObjsInRegionClosure(HeapRegion *hr, VerifyOption vo) + : _live_bytes(0), _hr(hr), _vo(vo) { + _g1h = G1CollectedHeap::heap(); + } + void do_object(oop o) { + VerifyLivenessOopClosure isLive(_g1h, _vo); + assert(o != NULL, "Huh?"); + if (!_g1h->is_obj_dead_cond(o, _vo)) { + // If the object is alive according to the mark word, + // then verify that the marking information agrees. + // Note we can't verify the contra-positive of the + // above: if the object is dead (according to the mark + // word), it may not be marked, or may have been marked + // but has since became dead, or may have been allocated + // since the last marking. + if (_vo == VerifyOption_G1UseMarkWord) { + guarantee(!_g1h->is_obj_dead(o), "mark word and concurrent mark mismatch"); + } + + o->oop_iterate_no_header(&isLive); + if (!_hr->obj_allocated_since_prev_marking(o)) { + size_t obj_size = o->size(); // Make sure we don't overflow + _live_bytes += (obj_size * HeapWordSize); + } + } + } + size_t live_bytes() { return _live_bytes; } +}; + +class VerifyArchiveOopClosure: public OopClosure { +public: + VerifyArchiveOopClosure(HeapRegion *hr) { } + void do_oop(narrowOop *p) { do_oop_work(p); } + void do_oop( oop *p) { do_oop_work(p); } + + template void do_oop_work(T *p) { + oop obj = oopDesc::load_decode_heap_oop(p); + guarantee(obj == NULL || G1MarkSweep::in_archive_range(obj), + "Archive object at " PTR_FORMAT " references a non-archive object at " PTR_FORMAT, + p2i(p), p2i(obj)); + } +}; + +class VerifyArchiveRegionClosure: public ObjectClosure { +public: + VerifyArchiveRegionClosure(HeapRegion *hr) { } + // Verify that all object pointers are to archive regions. + void do_object(oop o) { + VerifyArchiveOopClosure checkOop(NULL); + assert(o != NULL, "Should not be here for NULL oops"); + o->oop_iterate_no_header(&checkOop); + } +}; + +class VerifyRegionClosure: public HeapRegionClosure { +private: + bool _par; + VerifyOption _vo; + bool _failures; +public: + // _vo == UsePrevMarking -> use "prev" marking information, + // _vo == UseNextMarking -> use "next" marking information, + // _vo == UseMarkWord -> use mark word from object header. + VerifyRegionClosure(bool par, VerifyOption vo) + : _par(par), + _vo(vo), + _failures(false) {} + + bool failures() { + return _failures; + } + + bool doHeapRegion(HeapRegion* r) { + // For archive regions, verify there are no heap pointers to + // non-pinned regions. For all others, verify liveness info. + if (r->is_archive()) { + VerifyArchiveRegionClosure verify_oop_pointers(r); + r->object_iterate(&verify_oop_pointers); + return true; + } + if (!r->is_continues_humongous()) { + bool failures = false; + r->verify(_vo, &failures); + if (failures) { + _failures = true; + } else if (!r->is_starts_humongous()) { + VerifyObjsInRegionClosure not_dead_yet_cl(r, _vo); + r->object_iterate(¬_dead_yet_cl); + if (_vo != VerifyOption_G1UseNextMarking) { + if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) { + log_info(gc, verify)("[" PTR_FORMAT "," PTR_FORMAT "] max_live_bytes " SIZE_FORMAT " < calculated " SIZE_FORMAT, + p2i(r->bottom()), p2i(r->end()), r->max_live_bytes(), not_dead_yet_cl.live_bytes()); + _failures = true; + } + } else { + // When vo == UseNextMarking we cannot currently do a sanity + // check on the live bytes as the calculation has not been + // finalized yet. + } + } + } + return false; // stop the region iteration if we hit a failure + } +}; + +// This is the task used for parallel verification of the heap regions + +class G1ParVerifyTask: public AbstractGangTask { +private: + G1CollectedHeap* _g1h; + VerifyOption _vo; + bool _failures; + HeapRegionClaimer _hrclaimer; + +public: + // _vo == UsePrevMarking -> use "prev" marking information, + // _vo == UseNextMarking -> use "next" marking information, + // _vo == UseMarkWord -> use mark word from object header. + G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) : + AbstractGangTask("Parallel verify task"), + _g1h(g1h), + _vo(vo), + _failures(false), + _hrclaimer(g1h->workers()->active_workers()) {} + + bool failures() { + return _failures; + } + + void work(uint worker_id) { + HandleMark hm; + VerifyRegionClosure blk(true, _vo); + _g1h->heap_region_par_iterate(&blk, worker_id, &_hrclaimer); + if (blk.failures()) { + _failures = true; + } + } +}; + + +void G1HeapVerifier::verify(VerifyOption vo) { + if (!SafepointSynchronize::is_at_safepoint()) { + log_info(gc, verify)("Skipping verification. Not at safepoint."); + } + + assert(Thread::current()->is_VM_thread(), + "Expected to be executed serially by the VM thread at this point"); + + log_debug(gc, verify)("Roots"); + VerifyRootsClosure rootsCl(vo); + VerifyKlassClosure klassCl(_g1h, &rootsCl); + CLDToKlassAndOopClosure cldCl(&klassCl, &rootsCl, false); + + // We apply the relevant closures to all the oops in the + // system dictionary, class loader data graph, the string table + // and the nmethods in the code cache. + G1VerifyCodeRootOopClosure codeRootsCl(_g1h, &rootsCl, vo); + G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl); + + { + G1RootProcessor root_processor(_g1h, 1); + root_processor.process_all_roots(&rootsCl, + &cldCl, + &blobsCl); + } + + bool failures = rootsCl.failures() || codeRootsCl.failures(); + + if (vo != VerifyOption_G1UseMarkWord) { + // If we're verifying during a full GC then the region sets + // will have been torn down at the start of the GC. Therefore + // verifying the region sets will fail. So we only verify + // the region sets when not in a full GC. + log_debug(gc, verify)("HeapRegionSets"); + verify_region_sets(); + } + + log_debug(gc, verify)("HeapRegions"); + if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { + + G1ParVerifyTask task(_g1h, vo); + _g1h->workers()->run_task(&task); + if (task.failures()) { + failures = true; + } + + } else { + VerifyRegionClosure blk(false, vo); + _g1h->heap_region_iterate(&blk); + if (blk.failures()) { + failures = true; + } + } + + if (G1StringDedup::is_enabled()) { + log_debug(gc, verify)("StrDedup"); + G1StringDedup::verify(); + } + + if (failures) { + log_info(gc, verify)("Heap after failed verification:"); + // It helps to have the per-region information in the output to + // help us track down what went wrong. This is why we call + // print_extended_on() instead of print_on(). + LogHandle(gc, verify) log; + ResourceMark rm; + _g1h->print_extended_on(log.info_stream()); + } + guarantee(!failures, "there should not have been any failures"); +} + +// Heap region set verification + +class VerifyRegionListsClosure : public HeapRegionClosure { +private: + HeapRegionSet* _old_set; + HeapRegionSet* _humongous_set; + HeapRegionManager* _hrm; + +public: + uint _old_count; + uint _humongous_count; + uint _free_count; + + VerifyRegionListsClosure(HeapRegionSet* old_set, + HeapRegionSet* humongous_set, + HeapRegionManager* hrm) : + _old_set(old_set), _humongous_set(humongous_set), _hrm(hrm), + _old_count(), _humongous_count(), _free_count(){ } + + bool doHeapRegion(HeapRegion* hr) { + if (hr->is_young()) { + // TODO + } else if (hr->is_humongous()) { + assert(hr->containing_set() == _humongous_set, "Heap region %u is humongous but not in humongous set.", hr->hrm_index()); + _humongous_count++; + } else if (hr->is_empty()) { + assert(_hrm->is_free(hr), "Heap region %u is empty but not on the free list.", hr->hrm_index()); + _free_count++; + } else if (hr->is_old()) { + assert(hr->containing_set() == _old_set, "Heap region %u is old but not in the old set.", hr->hrm_index()); + _old_count++; + } else { + // There are no other valid region types. Check for one invalid + // one we can identify: pinned without old or humongous set. + assert(!hr->is_pinned(), "Heap region %u is pinned but not old (archive) or humongous.", hr->hrm_index()); + ShouldNotReachHere(); + } + return false; + } + + void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, HeapRegionManager* free_list) { + guarantee(old_set->length() == _old_count, "Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count); + guarantee(humongous_set->length() == _humongous_count, "Hum set count mismatch. Expected %u, actual %u.", humongous_set->length(), _humongous_count); + guarantee(free_list->num_free_regions() == _free_count, "Free list count mismatch. Expected %u, actual %u.", free_list->num_free_regions(), _free_count); + } +}; + +void G1HeapVerifier::verify_region_sets() { + assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); + + // First, check the explicit lists. + _g1h->_hrm.verify(); + { + // Given that a concurrent operation might be adding regions to + // the secondary free list we have to take the lock before + // verifying it. + MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); + _g1h->_secondary_free_list.verify_list(); + } + + // If a concurrent region freeing operation is in progress it will + // be difficult to correctly attributed any free regions we come + // across to the correct free list given that they might belong to + // one of several (free_list, secondary_free_list, any local lists, + // etc.). So, if that's the case we will skip the rest of the + // verification operation. Alternatively, waiting for the concurrent + // operation to complete will have a non-trivial effect on the GC's + // operation (no concurrent operation will last longer than the + // interval between two calls to verification) and it might hide + // any issues that we would like to catch during testing. + if (_g1h->free_regions_coming()) { + return; + } + + // Make sure we append the secondary_free_list on the free_list so + // that all free regions we will come across can be safely + // attributed to the free_list. + _g1h->append_secondary_free_list_if_not_empty_with_lock(); + + // Finally, make sure that the region accounting in the lists is + // consistent with what we see in the heap. + + VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_humongous_set, &_g1h->_hrm); + _g1h->heap_region_iterate(&cl); + cl.verify_counts(&_g1h->_old_set, &_g1h->_humongous_set, &_g1h->_hrm); +} + +void G1HeapVerifier::prepare_for_verify() { + if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { + _g1h->ensure_parsability(false); + } + _g1h->g1_rem_set()->prepare_for_verify(); +} + +double G1HeapVerifier::verify(bool guard, const char* msg) { + double verify_time_ms = 0.0; + + if (guard && _g1h->total_collections() >= VerifyGCStartAt) { + double verify_start = os::elapsedTime(); + HandleMark hm; // Discard invalid handles created during verification + prepare_for_verify(); + Universe::verify(VerifyOption_G1UsePrevMarking, msg); + verify_time_ms = (os::elapsedTime() - verify_start) * 1000; + } + + return verify_time_ms; +} + +void G1HeapVerifier::verify_before_gc() { + double verify_time_ms = verify(VerifyBeforeGC, "Before GC"); + _g1h->g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms); +} + +void G1HeapVerifier::verify_after_gc() { + double verify_time_ms = verify(VerifyAfterGC, "After GC"); + _g1h->g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms); +} + + +#ifndef PRODUCT +class G1VerifyCardTableCleanup: public HeapRegionClosure { + G1HeapVerifier* _verifier; + G1SATBCardTableModRefBS* _ct_bs; +public: + G1VerifyCardTableCleanup(G1HeapVerifier* verifier, G1SATBCardTableModRefBS* ct_bs) + : _verifier(verifier), _ct_bs(ct_bs) { } + virtual bool doHeapRegion(HeapRegion* r) { + if (r->is_survivor()) { + _verifier->verify_dirty_region(r); + } else { + _verifier->verify_not_dirty_region(r); + } + return false; + } +}; + +void G1HeapVerifier::verify_card_table_cleanup() { + if (G1VerifyCTCleanup || VerifyAfterGC) { + G1VerifyCardTableCleanup cleanup_verifier(this, _g1h->g1_barrier_set()); + _g1h->heap_region_iterate(&cleanup_verifier); + } +} + +void G1HeapVerifier::verify_not_dirty_region(HeapRegion* hr) { + // All of the region should be clean. + G1SATBCardTableModRefBS* ct_bs = _g1h->g1_barrier_set(); + MemRegion mr(hr->bottom(), hr->end()); + ct_bs->verify_not_dirty_region(mr); +} + +void G1HeapVerifier::verify_dirty_region(HeapRegion* hr) { + // We cannot guarantee that [bottom(),end()] is dirty. Threads + // dirty allocated blocks as they allocate them. The thread that + // retires each region and replaces it with a new one will do a + // maximal allocation to fill in [pre_dummy_top(),end()] but will + // not dirty that area (one less thing to have to do while holding + // a lock). So we can only verify that [bottom(),pre_dummy_top()] + // is dirty. + G1SATBCardTableModRefBS* ct_bs = _g1h->g1_barrier_set(); + MemRegion mr(hr->bottom(), hr->pre_dummy_top()); + if (hr->is_young()) { + ct_bs->verify_g1_young_region(mr); + } else { + ct_bs->verify_dirty_region(mr); + } +} + +void G1HeapVerifier::verify_dirty_young_list(HeapRegion* head) { + G1SATBCardTableModRefBS* ct_bs = _g1h->g1_barrier_set(); + for (HeapRegion* hr = head; hr != NULL; hr = hr->get_next_young_region()) { + verify_dirty_region(hr); + } +} + +void G1HeapVerifier::verify_dirty_young_regions() { + verify_dirty_young_list(_g1h->young_list()->first_region()); +} + +bool G1HeapVerifier::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, + HeapWord* tams, HeapWord* end) { + guarantee(tams <= end, + "tams: " PTR_FORMAT " end: " PTR_FORMAT, p2i(tams), p2i(end)); + HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end); + if (result < end) { + log_info(gc, verify)("## wrong marked address on %s bitmap: " PTR_FORMAT, bitmap_name, p2i(result)); + log_info(gc, verify)("## %s tams: " PTR_FORMAT " end: " PTR_FORMAT, bitmap_name, p2i(tams), p2i(end)); + return false; + } + return true; +} + +bool G1HeapVerifier::verify_bitmaps(const char* caller, HeapRegion* hr) { + CMBitMapRO* prev_bitmap = _g1h->concurrent_mark()->prevMarkBitMap(); + CMBitMapRO* next_bitmap = (CMBitMapRO*) _g1h->concurrent_mark()->nextMarkBitMap(); + + HeapWord* bottom = hr->bottom(); + HeapWord* ptams = hr->prev_top_at_mark_start(); + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* end = hr->end(); + + bool res_p = verify_no_bits_over_tams("prev", prev_bitmap, ptams, end); + + bool res_n = true; + // We reset mark_in_progress() before we reset _cmThread->in_progress() and in this window + // we do the clearing of the next bitmap concurrently. Thus, we can not verify the bitmap + // if we happen to be in that state. + if (_g1h->collector_state()->mark_in_progress() || !_g1h->_cmThread->in_progress()) { + res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end); + } + if (!res_p || !res_n) { + log_info(gc, verify)("#### Bitmap verification failed for " HR_FORMAT, HR_FORMAT_PARAMS(hr)); + log_info(gc, verify)("#### Caller: %s", caller); + return false; + } + return true; +} + +void G1HeapVerifier::check_bitmaps(const char* caller, HeapRegion* hr) { + if (!G1VerifyBitmaps) return; + + guarantee(verify_bitmaps(caller, hr), "bitmap verification"); +} + +class G1VerifyBitmapClosure : public HeapRegionClosure { +private: + const char* _caller; + G1HeapVerifier* _verifier; + bool _failures; + +public: + G1VerifyBitmapClosure(const char* caller, G1HeapVerifier* verifier) : + _caller(caller), _verifier(verifier), _failures(false) { } + + bool failures() { return _failures; } + + virtual bool doHeapRegion(HeapRegion* hr) { + bool result = _verifier->verify_bitmaps(_caller, hr); + if (!result) { + _failures = true; + } + return false; + } +}; + +void G1HeapVerifier::check_bitmaps(const char* caller) { + if (!G1VerifyBitmaps) return; + + G1VerifyBitmapClosure cl(caller, this); + _g1h->heap_region_iterate(&cl); + guarantee(!cl.failures(), "bitmap verification"); +} + +class G1CheckCSetFastTableClosure : public HeapRegionClosure { + private: + bool _failures; + public: + G1CheckCSetFastTableClosure() : HeapRegionClosure(), _failures(false) { } + + virtual bool doHeapRegion(HeapRegion* hr) { + uint i = hr->hrm_index(); + InCSetState cset_state = (InCSetState) G1CollectedHeap::heap()->_in_cset_fast_test.get_by_index(i); + if (hr->is_humongous()) { + if (hr->in_collection_set()) { + log_info(gc, verify)("## humongous region %u in CSet", i); + _failures = true; + return true; + } + if (cset_state.is_in_cset()) { + log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for humongous region %u", cset_state.value(), i); + _failures = true; + return true; + } + if (hr->is_continues_humongous() && cset_state.is_humongous()) { + log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for continues humongous region %u", cset_state.value(), i); + _failures = true; + return true; + } + } else { + if (cset_state.is_humongous()) { + log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for non-humongous region %u", cset_state.value(), i); + _failures = true; + return true; + } + if (hr->in_collection_set() != cset_state.is_in_cset()) { + log_info(gc, verify)("## in CSet %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u", + hr->in_collection_set(), cset_state.value(), i); + _failures = true; + return true; + } + if (cset_state.is_in_cset()) { + if (hr->is_young() != (cset_state.is_young())) { + log_info(gc, verify)("## is_young %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u", + hr->is_young(), cset_state.value(), i); + _failures = true; + return true; + } + if (hr->is_old() != (cset_state.is_old())) { + log_info(gc, verify)("## is_old %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u", + hr->is_old(), cset_state.value(), i); + _failures = true; + return true; + } + } + } + return false; + } + + bool failures() const { return _failures; } +}; + +bool G1HeapVerifier::check_cset_fast_test() { + G1CheckCSetFastTableClosure cl; + _g1h->_hrm.iterate(&cl); + return !cl.failures(); +} +#endif // PRODUCT diff --git a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp new file mode 100644 index 00000000000..c4fdb0d1057 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#ifndef SHARE_VM_GC_G1_G1HEAPVERIFIER_HPP +#define SHARE_VM_GC_G1_G1HEAPVERIFIER_HPP + +#include "gc/g1/heapRegionSet.hpp" +#include "memory/allocation.hpp" +#include "memory/universe.hpp" + +class G1CollectedHeap; + +class G1HeapVerifier : public CHeapObj { +private: + G1CollectedHeap* _g1h; + + // verify_region_sets() performs verification over the region + // lists. It will be compiled in the product code to be used when + // necessary (i.e., during heap verification). + void verify_region_sets(); + +public: + + G1HeapVerifier(G1CollectedHeap* heap) : _g1h(heap) { } + + // Perform verification. + + // vo == UsePrevMarking -> use "prev" marking information, + // vo == UseNextMarking -> use "next" marking information + // vo == UseMarkWord -> use the mark word in the object header + // + // NOTE: Only the "prev" marking information is guaranteed to be + // consistent most of the time, so most calls to this should use + // vo == UsePrevMarking. + // Currently, there is only one case where this is called with + // vo == UseNextMarking, which is to verify the "next" marking + // information at the end of remark. + // Currently there is only one place where this is called with + // vo == UseMarkWord, which is to verify the marking during a + // full GC. + void verify(VerifyOption vo); + + // verify_region_sets_optional() is planted in the code for + // list verification in non-product builds (and it can be enabled in + // product builds by defining HEAP_REGION_SET_FORCE_VERIFY to be 1). +#if HEAP_REGION_SET_FORCE_VERIFY + void verify_region_sets_optional() { + verify_region_sets(); + } +#else // HEAP_REGION_SET_FORCE_VERIFY + void verify_region_sets_optional() { } +#endif // HEAP_REGION_SET_FORCE_VERIFY + + void prepare_for_verify(); + double verify(bool guard, const char* msg); + void verify_before_gc(); + void verify_after_gc(); + +#ifndef PRODUCT + // Make sure that the given bitmap has no marked objects in the + // range [from,limit). If it does, print an error message and return + // false. Otherwise, just return true. bitmap_name should be "prev" + // or "next". + bool verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, + HeapWord* from, HeapWord* limit); + + // Verify that the prev / next bitmap range [tams,end) for the given + // region has no marks. Return true if all is well, false if errors + // are detected. + bool verify_bitmaps(const char* caller, HeapRegion* hr); +#endif // PRODUCT + + // If G1VerifyBitmaps is set, verify that the marking bitmaps for + // the given region do not have any spurious marks. If errors are + // detected, print appropriate error messages and crash. + void check_bitmaps(const char* caller, HeapRegion* hr) PRODUCT_RETURN; + + // If G1VerifyBitmaps is set, verify that the marking bitmaps do not + // have any spurious marks. If errors are detected, print + // appropriate error messages and crash. + void check_bitmaps(const char* caller) PRODUCT_RETURN; + + // Do sanity check on the contents of the in-cset fast test table. + bool check_cset_fast_test() PRODUCT_RETURN_( return true; ); + + void verify_card_table_cleanup() PRODUCT_RETURN; + + void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN; + void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN; + void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN; + void verify_dirty_young_regions() PRODUCT_RETURN; +}; + +#endif // SHARE_VM_GC_G1_G1HEAPVERIFIER_HPP From e95747daf1bc329d3d56a1c60ce5fd58cb20b370 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 26 Jan 2016 21:18:08 -0500 Subject: [PATCH 007/139] 8145740: Visual Studio pragmas should be guarded by ifdef _MSC_VER Reviewed-by: simonis, dholmes --- hotspot/src/share/vm/utilities/growableArray.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/utilities/growableArray.hpp b/hotspot/src/share/vm/utilities/growableArray.hpp index e4a414a0cdc..933cf339661 100644 --- a/hotspot/src/share/vm/utilities/growableArray.hpp +++ b/hotspot/src/share/vm/utilities/growableArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,9 @@ template class GrowableArray : public GenericGrowableArray { : GenericGrowableArray(initial_size, 0, C_heap, F) { _data = (E*)raw_allocate(sizeof(E)); // Needed for Visual Studio 2012 and older +#ifdef _MSC_VER #pragma warning(suppress: 4345) +#endif for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E(); } @@ -422,7 +424,9 @@ template void GrowableArray::grow(int j) { int i = 0; for ( ; i < _len; i++) ::new ((void*)&newData[i]) E(_data[i]); // Needed for Visual Studio 2012 and older +#ifdef _MSC_VER #pragma warning(suppress: 4345) +#endif for ( ; i < _max; i++) ::new ((void*)&newData[i]) E(); for (i = 0; i < old_max; i++) _data[i].~E(); if (on_C_heap() && _data != NULL) { From 127158a21099a833450390cfd4507aa34b63a8d8 Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Wed, 27 Jan 2016 09:07:10 +0100 Subject: [PATCH 008/139] 8147348: LogTagLevelExpression not properly initialized in configure_stdout Reviewed-by: brutisso, sla --- hotspot/src/share/vm/logging/log.cpp | 97 ++++++++++--------- .../vm/logging/logTagLevelExpression.cpp | 13 --- .../vm/logging/logTagLevelExpression.hpp | 12 ++- .../share/vm/utilities/internalVMTests.cpp | 2 + 4 files changed, 65 insertions(+), 59 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 71ca3a3e22f..c2741537826 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -36,52 +36,54 @@ void Test_log_length() { remove("loglengthoutput.txt"); // Write long message to output file - LogConfiguration::parse_log_arguments("loglengthoutput.txt", "logging=trace", - NULL, NULL, NULL); ResourceMark rm; - outputStream* logstream = LogHandle(logging)::trace_stream(); - logstream->print_cr("01:1234567890-" - "02:1234567890-" - "03:1234567890-" - "04:1234567890-" - "05:1234567890-" - "06:1234567890-" - "07:1234567890-" - "08:1234567890-" - "09:1234567890-" - "10:1234567890-" - "11:1234567890-" - "12:1234567890-" - "13:1234567890-" - "14:1234567890-" - "15:1234567890-" - "16:1234567890-" - "17:1234567890-" - "18:1234567890-" - "19:1234567890-" - "20:1234567890-" - "21:1234567890-" - "22:1234567890-" - "23:1234567890-" - "24:1234567890-" - "25:1234567890-" - "26:1234567890-" - "27:1234567890-" - "28:1234567890-" - "29:1234567890-" - "30:1234567890-" - "31:1234567890-" - "32:1234567890-" - "33:1234567890-" - "34:1234567890-" - "35:1234567890-" - "36:1234567890-" - "37:1234567890-"); + LogHandle(logging) log; + bool success = LogConfiguration::parse_log_arguments("loglengthoutput.txt", "logging=trace", + NULL, NULL, log.error_stream()); + assert(success, "test unable to configure logging"); + log.trace("01:1234567890-" + "02:1234567890-" + "03:1234567890-" + "04:1234567890-" + "05:1234567890-" + "06:1234567890-" + "07:1234567890-" + "08:1234567890-" + "09:1234567890-" + "10:1234567890-" + "11:1234567890-" + "12:1234567890-" + "13:1234567890-" + "14:1234567890-" + "15:1234567890-" + "16:1234567890-" + "17:1234567890-" + "18:1234567890-" + "19:1234567890-" + "20:1234567890-" + "21:1234567890-" + "22:1234567890-" + "23:1234567890-" + "24:1234567890-" + "25:1234567890-" + "26:1234567890-" + "27:1234567890-" + "28:1234567890-" + "29:1234567890-" + "30:1234567890-" + "31:1234567890-" + "32:1234567890-" + "33:1234567890-" + "34:1234567890-" + "35:1234567890-" + "36:1234567890-" + "37:1234567890-"); + LogConfiguration::parse_log_arguments("loglengthoutput.txt", "all=off", + NULL, NULL, log.error_stream()); // Look for end of message in output file - FILE* fp; - fp = fopen("loglengthoutput.txt", "r"); - assert (fp, "File read error"); + FILE* fp = fopen("loglengthoutput.txt", "r"); + assert(fp, "File read error"); char output[600]; if (fgets(output, 600, fp) != NULL) { assert(strstr(output, "37:1234567890-"), "logging print size error"); @@ -89,5 +91,12 @@ void Test_log_length() { fclose(fp); remove("loglengthoutput.txt"); } -#endif // PRODUCT +void Test_configure_stdout() { + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(logging)); + assert(log_is_enabled(Info, logging), "configure_stdout did not enable requested logging"); + assert(!log_is_enabled(Info, logging, gc), "configure_stdout enabled too much logging"); + LogConfiguration::configure_stdout(LogLevel::Off, false, LOG_TAGS(logging)); + assert(!log_is_enabled(Info, logging), "configure_stdout did not disable requested logging"); +} +#endif // PRODUCT diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.cpp b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp index 2213ee3e70b..0770c38ba8d 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.cpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.cpp @@ -29,21 +29,8 @@ const char* LogTagLevelExpression::DefaultExpressionString = "all"; -void LogTagLevelExpression::clear() { - _ntags = 0; - _ncombinations = 0; - for (size_t combination = 0; combination < MaxCombinations; combination++) { - _level[combination] = LogLevel::Invalid; - _allow_other_tags[combination] = false; - for (size_t tag = 0; tag < LogTag::MaxTags; tag++) { - _tags[combination][tag] = LogTag::__NO_TAG; - } - } -} - bool LogTagLevelExpression::parse(const char* str, outputStream* errstream) { bool success = true; - clear(); if (str == NULL || strcmp(str, "") == 0) { str = DefaultExpressionString; } diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp index 34163222989..1eb27f07517 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp @@ -47,6 +47,11 @@ class LogTagLevelExpression : public StackObj { bool _allow_other_tags[MaxCombinations]; void new_combination() { + // Make sure either all tags are set or the last tag is __NO_TAG + if (_ntags < LogTag::MaxTags) { + _tags[_ncombinations][_ntags] = LogTag::__NO_TAG; + } + _ncombinations++; _ntags = 0; } @@ -64,10 +69,13 @@ class LogTagLevelExpression : public StackObj { _allow_other_tags[_ncombinations] = true; } - void clear(); - public: LogTagLevelExpression() : _ntags(0), _ncombinations(0) { + for (size_t combination = 0; combination < MaxCombinations; combination++) { + _level[combination] = LogLevel::Invalid; + _allow_other_tags[combination] = false; + _tags[combination][0] = LogTag::__NO_TAG; + } } bool parse(const char* str, outputStream* errstream = NULL); diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 9b7395e3514..d74223eb791 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -53,6 +53,7 @@ void Test_linked_list(); void TestResourcehash_test(); void TestChunkedList_test(); void Test_log_length(); +void Test_configure_stdout(); void Test_TempNewSymbol(); void GlobalDefinitions_test(); void GCTimer_test(); @@ -110,6 +111,7 @@ void InternalVMTests::run() { run_unit_test(TestChunkedList_test()); run_unit_test(JSON_test()); run_unit_test(Test_log_length()); + run_unit_test(Test_configure_stdout()); run_unit_test(DirectivesParser_test()); run_unit_test(Test_TempNewSymbol()); #if INCLUDE_VM_STRUCTS From 480e92f8b5599cf2576d55e651f1d839a2a8375b Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 27 Jan 2016 11:51:56 +0100 Subject: [PATCH 009/139] 8146905: cleanup ostream, staticBufferStream Get rid of staticBufferStream and implement the use-caller-provided-scratch-buffer feature in a simpler way. Reviewed-by: simonis, dholmes --- hotspot/src/share/vm/utilities/ostream.cpp | 94 +++++++--------------- hotspot/src/share/vm/utilities/ostream.hpp | 35 ++++---- hotspot/src/share/vm/utilities/vmError.cpp | 18 +++-- 3 files changed, 54 insertions(+), 93 deletions(-) diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index d3583a006ff..d37b9d08494 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,8 @@ outputStream::outputStream(int width) { _newlines = 0; _precount = 0; _indentation = 0; + _scratch = NULL; + _scratch_len = 0; } outputStream::outputStream(int width, bool has_time_stamps) { @@ -52,6 +54,8 @@ outputStream::outputStream(int width, bool has_time_stamps) { _newlines = 0; _precount = 0; _indentation = 0; + _scratch = NULL; + _scratch_len = 0; if (has_time_stamps) _stamp.update(); } @@ -119,38 +123,47 @@ const char* outputStream::do_vsnprintf(char* buffer, size_t buflen, return result; } -void outputStream::print(const char* format, ...) { +void outputStream::do_vsnprintf_and_write_with_automatic_buffer(const char* format, va_list ap, bool add_cr) { char buffer[O_BUFLEN]; + size_t len; + const char* str = do_vsnprintf(buffer, sizeof(buffer), format, ap, add_cr, len); + write(str, len); +} + +void outputStream::do_vsnprintf_and_write_with_scratch_buffer(const char* format, va_list ap, bool add_cr) { + size_t len; + const char* str = do_vsnprintf(_scratch, _scratch_len, format, ap, add_cr, len); + write(str, len); +} + +void outputStream::do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) { + if (_scratch) { + do_vsnprintf_and_write_with_scratch_buffer(format, ap, add_cr); + } else { + do_vsnprintf_and_write_with_automatic_buffer(format, ap, add_cr); + } +} + +void outputStream::print(const char* format, ...) { va_list ap; va_start(ap, format); - size_t len; - const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len); - write(str, len); + do_vsnprintf_and_write(format, ap, false); va_end(ap); } void outputStream::print_cr(const char* format, ...) { - char buffer[O_BUFLEN]; va_list ap; va_start(ap, format); - size_t len; - const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len); - write(str, len); + do_vsnprintf_and_write(format, ap, true); va_end(ap); } void outputStream::vprint(const char *format, va_list argptr) { - char buffer[O_BUFLEN]; - size_t len; - const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len); - write(str, len); + do_vsnprintf_and_write(format, argptr, false); } void outputStream::vprint_cr(const char* format, va_list argptr) { - char buffer[O_BUFLEN]; - size_t len; - const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len); - write(str, len); + do_vsnprintf_and_write(format, argptr, true); } void outputStream::fill_to(int col) { @@ -958,53 +971,6 @@ void ostream_abort() { } } -staticBufferStream::staticBufferStream(char* buffer, size_t buflen, - outputStream *outer_stream) { - _buffer = buffer; - _buflen = buflen; - _outer_stream = outer_stream; - // compile task prints time stamp relative to VM start - _stamp.update_to(1); -} - -void staticBufferStream::write(const char* c, size_t len) { - _outer_stream->print_raw(c, (int)len); -} - -void staticBufferStream::flush() { - _outer_stream->flush(); -} - -void staticBufferStream::print(const char* format, ...) { - va_list ap; - va_start(ap, format); - size_t len; - const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len); - write(str, len); - va_end(ap); -} - -void staticBufferStream::print_cr(const char* format, ...) { - va_list ap; - va_start(ap, format); - size_t len; - const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len); - write(str, len); - va_end(ap); -} - -void staticBufferStream::vprint(const char *format, va_list argptr) { - size_t len; - const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len); - write(str, len); -} - -void staticBufferStream::vprint_cr(const char* format, va_list argptr) { - size_t len; - const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len); - write(str, len); -} - bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() { buffer_length = initial_size; buffer = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp index 627ba90fb92..def5a44a405 100644 --- a/hotspot/src/share/vm/utilities/ostream.hpp +++ b/hotspot/src/share/vm/utilities/ostream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 +49,8 @@ class outputStream : public ResourceObj { int _newlines; // number of '\n' output so far julong _precount; // number of chars output, less _position TimeStamp _stamp; // for time stamps + char* _scratch; // internal scratch buffer for printf + size_t _scratch_len; // size of internal scratch buffer void update_position(const char* s, size_t len); static const char* do_vsnprintf(char* buffer, size_t buflen, @@ -56,6 +58,13 @@ class outputStream : public ResourceObj { bool add_cr, size_t& result_len) ATTRIBUTE_PRINTF(3, 0); + // calls do_vsnprintf and writes output to stream; uses an on-stack buffer. + void do_vsnprintf_and_write_with_automatic_buffer(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); + // calls do_vsnprintf and writes output to stream; uses the user-provided buffer; + void do_vsnprintf_and_write_with_scratch_buffer(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); + // calls do_vsnprintf, then writes output to stream. + void do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); + public: // creation outputStream(int width = 80); @@ -119,6 +128,10 @@ class outputStream : public ResourceObj { virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation virtual ~outputStream() {} // close properly on deletion + // Caller may specify their own scratch buffer to use for printing; otherwise, + // an automatic buffer on the stack (with O_BUFLEN len) is used. + void set_scratch_buffer(char* p, size_t len) { _scratch = p; _scratch_len = len; } + void dec_cr() { dec(); cr(); } void inc_cr() { inc(); cr(); } }; @@ -250,26 +263,6 @@ void ostream_init_log(); void ostream_exit(); void ostream_abort(); -// staticBufferStream uses a user-supplied buffer for all formatting. -// Used for safe formatting during fatal error handling. Not MT safe. -// Do not share the stream between multiple threads. -class staticBufferStream : public outputStream { - private: - char* _buffer; - size_t _buflen; - outputStream* _outer_stream; - public: - staticBufferStream(char* buffer, size_t buflen, - outputStream *outer_stream); - ~staticBufferStream() {}; - virtual void write(const char* c, size_t len); - void flush(); - void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); - void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); - void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); - void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); -}; - // In the non-fixed buffer case an underlying buffer will be created and // managed in C heap. Not MT-safe. class bufferedStream : public outputStream { diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index a1bf6ef195d..9e37c98d693 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -987,10 +987,12 @@ void VMError::print_vm_info(outputStream* st) { volatile intptr_t VMError::first_error_tid = -1; // An error could happen before tty is initialized or after it has been -// destroyed. Here we use a very simple unbuffered fdStream for printing. -// Only out.print_raw() and out.print_raw_cr() should be used, as other -// printing methods need to allocate large buffer on stack. To format a -// string, use jio_snprintf() with a static buffer or use staticBufferStream. +// destroyed. +// Please note: to prevent large stack allocations, the log- and +// output-stream use a global scratch buffer for format printing. +// (see VmError::report_and_die(). Access to those streams is synchronized +// in VmError::report_and_die() - there is only one reporting thread at +// any given time. fdStream VMError::out(defaultStream::output_fd()); fdStream VMError::log; // error log used by VMError::report_and_die() @@ -1100,6 +1102,8 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt { // Don't allocate large buffer on stack static char buffer[O_BUFLEN]; + out.set_scratch_buffer(buffer, sizeof(buffer)); + log.set_scratch_buffer(buffer, sizeof(buffer)); // How many errors occurred in error handler when reporting first_error. static int recursive_error_count; @@ -1186,8 +1190,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt // print to screen if (!out_done) { - staticBufferStream sbs(buffer, sizeof(buffer), &out); - report(&sbs, false); + report(&out, false); out_done = true; @@ -1215,8 +1218,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt } } - staticBufferStream sbs(buffer, O_BUFLEN, &log); - report(&sbs, true); + report(&log, true); _current_step = 0; _current_step_info = ""; From 64dd8e763d4628f1f56be6b6f8295c217f4e25be Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 27 Jan 2016 07:14:56 -0500 Subject: [PATCH 010/139] 8137314: vm crash from test java/security/Policy/SignedJar/SignedJarTest.java Add additional checks in the verifier for recursive verification Reviewed-by: acorn, gtriantafill --- hotspot/src/share/vm/classfile/verifier.cpp | 25 +++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index c2759287c3f..b5a827b7c10 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -651,6 +651,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { int ex_max = -1; // Look through each item on the exception table. Each of the fields must refer // to a legal instruction. + if (was_recursively_verified()) return; verify_exception_handler_table( code_length, code_data, ex_min, ex_max, CHECK_VERIFY(this)); @@ -737,11 +738,14 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { // should be used for this check. So, do the check here before a possible // local is added to the type state. if (Bytecodes::is_store_into_local(opcode) && bci >= ex_min && bci < ex_max) { + if (was_recursively_verified()) return; verify_exception_handler_targets( bci, this_uninit, ¤t_frame, &stackmap_table, CHECK_VERIFY(this)); verified_exc_handlers = true; } + if (was_recursively_verified()) return; + switch (opcode) { case Bytecodes::_nop : no_control_flow = false; break; @@ -1730,6 +1734,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { assert(!(verified_exc_handlers && this_uninit), "Exception handler targets got verified before this_uninit got set"); if (!verified_exc_handlers && bci >= ex_min && bci < ex_max) { + if (was_recursively_verified()) return; verify_exception_handler_targets( bci, this_uninit, ¤t_frame, &stackmap_table, CHECK_VERIFY(this)); } @@ -1767,6 +1772,9 @@ char* ClassVerifier::generate_code_data(const methodHandle& m, u4 code_length, T return code_data; } +// Since this method references the constant pool, call was_recursively_verified() +// before calling this method to make sure a prior class load did not cause the +// current class to get verified. void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS) { ExceptionTable exhandlers(_method()); int exlength = exhandlers.length(); @@ -1874,7 +1882,11 @@ u2 ClassVerifier::verify_stackmap_table(u2 stackmap_index, u2 bci, return stackmap_index; } -void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, StackMapFrame* current_frame, +// Since this method references the constant pool, call was_recursively_verified() +// before calling this method to make sure a prior class load did not cause the +// current class to get verified. +void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, + StackMapFrame* current_frame, StackMapTable* stackmap_table, TRAPS) { constantPoolHandle cp (THREAD, _method->constants()); ExceptionTable exhandlers(_method()); @@ -1889,6 +1901,7 @@ void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, S if (this_uninit) { flags |= FLAG_THIS_UNINIT; } StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags); if (catch_type_index != 0) { + if (was_recursively_verified()) return; // We know that this index refers to a subclass of Throwable VerificationType catch_type = cp_index_to_type( catch_type_index, cp, CHECK_VERIFY(this)); @@ -2269,6 +2282,7 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, check_protected: { if (_this_type == stack_object_type) break; // stack_object_type must be assignable to _current_class_type + if (was_recursively_verified()) return; Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(index)); if (!name_in_supers(ref_class_name, current_class())) @@ -2531,6 +2545,7 @@ void ClassVerifier::verify_invoke_init( // Check the exception handler target stackmaps with the locals from the // incoming stackmap (before initialize_object() changes them to outgoing // state). + if (was_recursively_verified()) return; verify_exception_handler_targets(bci, true, current_frame, stackmap_table, CHECK_VERIFY(this)); } // in_try_block @@ -2548,6 +2563,7 @@ void ClassVerifier::verify_invoke_init( return; } u2 new_class_index = Bytes::get_Java_u2(new_bcp + 1); + if (was_recursively_verified()) return; verify_cp_class_type(bci, new_class_index, cp, CHECK_VERIFY(this)); // The method must be an method of the indicated class @@ -2567,6 +2583,7 @@ void ClassVerifier::verify_invoke_init( VerificationType objectref_type = new_class_type; if (name_in_supers(ref_class_type.name(), current_class())) { Klass* ref_klass = load_class(ref_class_type.name(), CHECK); + if (was_recursively_verified()) return; Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method( vmSymbols::object_initializer_name(), cp->signature_ref_at(bcs->get_index_u2()), @@ -2591,6 +2608,7 @@ void ClassVerifier::verify_invoke_init( // incoming stackmap (before initialize_object() changes them to outgoing // state). if (in_try_block) { + if (was_recursively_verified()) return; verify_exception_handler_targets(bci, *this_uninit, current_frame, stackmap_table, CHECK_VERIFY(this)); } @@ -2791,6 +2809,7 @@ void ClassVerifier::verify_invoke_instructions( verify_invoke_init(bcs, index, ref_class_type, current_frame, code_length, in_try_block, this_uninit, cp, stackmap_table, CHECK_VERIFY(this)); + if (was_recursively_verified()) return; } else { // other methods // Ensures that target class is assignable to method class. if (opcode == Bytecodes::_invokespecial) { @@ -2816,6 +2835,7 @@ void ClassVerifier::verify_invoke_instructions( VerificationType stack_object_type = current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this)); if (current_type() != stack_object_type) { + if (was_recursively_verified()) return; assert(cp->cache() == NULL, "not rewritten yet"); Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(index)); @@ -2894,6 +2914,7 @@ void ClassVerifier::verify_anewarray( current_frame->pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); + if (was_recursively_verified()) return; VerificationType component_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); int length; From 1163c0a2cb2a7ee2042942ee09c223e32f4140e9 Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Wed, 27 Jan 2016 14:50:56 +0100 Subject: [PATCH 011/139] 8147461: Use byte offsets for vtable start and vtable length offsets Reviewed-by: cjplummer, coleenp, dnsimon --- .../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 8 ++++---- .../src/cpu/aarch64/vm/vtableStubs_aarch64.cpp | 4 ++-- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 10 +++++----- hotspot/src/cpu/ppc/vm/ppc.ad | 6 +++--- hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp | 6 +++--- hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp | 14 +++++++------- .../src/cpu/sparc/vm/macroAssembler_sparc.cpp | 16 ++++++++-------- hotspot/src/cpu/sparc/vm/sparc.ad | 10 +++++----- hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp | 4 ++-- hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp | 4 ++-- hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 8 ++++---- hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp | 4 ++-- hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp | 4 ++-- .../hotspot/HotSpotResolvedJavaMethodImpl.java | 4 ++-- .../src/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 9 +-------- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 6 +++--- hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp | 4 ++-- hotspot/src/share/vm/oops/instanceKlass.hpp | 6 +++--- hotspot/src/share/vm/oops/klassVtable.hpp | 5 ++++- hotspot/src/share/vm/opto/library_call.cpp | 6 +++--- .../src/share/vm/shark/sharkTopLevelBlock.cpp | 12 ++++++------ 21 files changed, 73 insertions(+), 77 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index e3b39b08f39..9cf1dc31ff8 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -898,13 +898,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, "caller must use same register for non-constant itable index as for method"); // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; + int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); int itentry_off = itableMethodEntry::method_offset_in_bytes(); int scan_step = itableOffsetEntry::size() * wordSize; - int vte_size = vtableEntry::size() * wordSize; + int vte_size = vtableEntry::size_in_bytes(); assert(vte_size == wordSize, "else adjust times_vte_scale"); - ldrw(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset() * wordSize)); + ldrw(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset())); // %%% Could store the aligned, prescaled offset in the klassoop. // lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); @@ -958,7 +958,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, void MacroAssembler::lookup_virtual_method(Register recv_klass, RegisterOrConstant vtable_index, Register method_result) { - const int base = InstanceKlass::vtable_start_offset() * wordSize; + const int base = in_bytes(InstanceKlass::vtable_start_offset()); assert(vtableEntry::size() * wordSize == 8, "adjust the scaling in the code below"); int vtable_offset_in_bytes = base + vtableEntry::method_offset_in_bytes(); diff --git a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp index 34b6c5caa03..56d4254efc2 100644 --- a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -73,7 +73,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { if (DebugVtables) { Label L; // check offset vs vtable length - __ ldrw(rscratch1, Address(r19, InstanceKlass::vtable_length_offset() * wordSize)); + __ ldrw(rscratch1, Address(r19, InstanceKlass::vtable_length_offset())); __ cmpw(rscratch1, vtable_index * vtableEntry::size()); __ br(Assembler::GT, L); __ enter(); diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index fae424b569e..fc6556481c9 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2015 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1583,13 +1583,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, "caller must use same register for non-constant itable index as for method"); // Compute start of first itableOffsetEntry (which is at the end of the vtable). - int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; + int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); int itentry_off = itableMethodEntry::method_offset_in_bytes(); int logMEsize = exact_log2(itableMethodEntry::size() * wordSize); int scan_step = itableOffsetEntry::size() * wordSize; - int log_vte_size= exact_log2(vtableEntry::size() * wordSize); + int log_vte_size= exact_log2(vtableEntry::size_in_bytes()); - lwz(scan_temp, InstanceKlass::vtable_length_offset() * wordSize, recv_klass); + lwz(scan_temp, in_bytes(InstanceKlass::vtable_length_offset()), recv_klass); // %%% We should store the aligned, prescaled offset in the klassoop. // Then the next several instructions would fold away. @@ -1657,7 +1657,7 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass, assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); - const int base = InstanceKlass::vtable_start_offset() * wordSize; + const int base = in_bytes(InstanceKlass::vtable_start_offset()); assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); if (vtable_index.is_register()) { diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 001b539399f..4516efb4ae3 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. // Copyright 2012, 2015 SAP AG. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -3562,8 +3562,8 @@ encode %{ __ load_klass(R11_scratch1, R3); - int entry_offset = InstanceKlass::vtable_start_offset() + _vtable_index * vtableEntry::size(); - int v_off = entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); + int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + _vtable_index * vtableEntry::size_in_bytes(); + int v_off = entry_offset + vtableEntry::method_offset_in_bytes(); __ li(R19_method, v_off); __ ldx(R19_method/*method oop*/, R19_method/*method offset*/, R11_scratch1/*class*/); // NOTE: for vtable dispatches, the vtable entry will never be diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index ec92898e890..f963ffd70bc 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2013, 2015 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -3282,9 +3282,9 @@ void TemplateTable::generate_vtable_call(Register Rrecv_klass, Register Rindex, const Register Rtarget_method = Rindex; // Get target method & entry point. - const int base = InstanceKlass::vtable_start_offset() * wordSize; + const int base = in_bytes(InstanceKlass::vtable_start_offset()); // Calc vtable addr scale the vtable index by 8. - __ sldi(Rindex, Rindex, exact_log2(vtableEntry::size() * wordSize)); + __ sldi(Rindex, Rindex, exact_log2(vtableEntry::size_in_bytes())); // Load target. __ addi(Rrecv_klass, Rrecv_klass, base + vtableEntry::method_offset_in_bytes()); __ ldx(Rtarget_method, Rindex, Rrecv_klass); diff --git a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp index d19c211300f..77c97b129eb 100644 --- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2015 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -80,14 +80,14 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { __ load_klass(rcvr_klass, R3); // Set method (in case of interpreted method), and destination address. - int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); + int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); #ifndef PRODUCT if (DebugVtables) { Label L; // Check offset vs vtable length. const Register vtable_len = R12_scratch2; - __ lwz(vtable_len, InstanceKlass::vtable_length_offset()*wordSize, rcvr_klass); + __ lwz(vtable_len, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); __ cmpwi(CCR0, vtable_len, vtable_index*vtableEntry::size()); __ bge(CCR0, L); __ li(R12_scratch2, vtable_index); @@ -96,7 +96,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { } #endif - int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); + int v_off = entry_offset + vtableEntry::method_offset_in_bytes(); __ ld(R19_method, v_off, rcvr_klass); @@ -163,13 +163,13 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { __ load_klass(rcvr_klass, R3_ARG1); BLOCK_COMMENT("Load start of itable entries into itable_entry."); - __ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass); - __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize)); + __ lwz(vtable_len, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); + __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); __ add(itable_entry_addr, vtable_len, rcvr_klass); // Loop over all itable entries until desired interfaceOop(Rinterface) found. BLOCK_COMMENT("Increment itable_entry_addr in loop."); - const int vtable_base_offset = InstanceKlass::vtable_start_offset() * wordSize; + const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); __ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes()); const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index 61122127c96..130a7c9b966 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -2188,16 +2188,16 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; + int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); int scan_step = itableOffsetEntry::size() * wordSize; - int vte_size = vtableEntry::size() * wordSize; + int vte_size = vtableEntry::size_in_bytes(); - lduw(recv_klass, InstanceKlass::vtable_length_offset() * wordSize, scan_temp); + lduw(recv_klass, in_bytes(InstanceKlass::vtable_length_offset()), scan_temp); // %%% We should store the aligned, prescaled offset in the klassoop. // Then the next several instructions would fold away. int itb_offset = vtable_base; - int itb_scale = exact_log2(vtableEntry::size() * wordSize); + int itb_scale = exact_log2(vtableEntry::size_in_bytes()); sll(scan_temp, itb_scale, scan_temp); add(scan_temp, itb_offset, scan_temp); add(recv_klass, scan_temp, scan_temp); @@ -2268,16 +2268,16 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass, Register method_result) { assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); Register sethi_temp = method_result; - const int base = (InstanceKlass::vtable_start_offset() * wordSize + - // method pointer offset within the vtable entry: - vtableEntry::method_offset_in_bytes()); + const int base = in_bytes(InstanceKlass::vtable_start_offset()) + + // method pointer offset within the vtable entry: + vtableEntry::method_offset_in_bytes(); RegisterOrConstant vtable_offset = vtable_index; // Each of the following three lines potentially generates an instruction. // But the total number of address formation instructions will always be // at most two, and will often be zero. In any case, it will be optimal. // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x). // If vtable_index is a constant, we will have at most (set B+X<vtable_index() * vtableEntry::size(); - int vtable_offset = entry_offset * wordSize + vtableEntry::method_offset_in_bytes(); + int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + x->vtable_index() * vtableEntry::size_in_bytes(); + int vtable_offset = entry_offset + vtableEntry::method_offset_in_bytes(); __ call_virtual(target, receiver, result_register, vtable_offset, arg_list, info); } break; diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index c1be4987bf2..6926a77392a 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -151,8 +151,8 @@ jbyte* CompilerToVM::Data::cardtable_start_address; int CompilerToVM::Data::cardtable_shift; void CompilerToVM::Data::initialize() { - InstanceKlass_vtable_start_offset = InstanceKlass::vtable_start_offset(); - InstanceKlass_vtable_length_offset = InstanceKlass::vtable_length_offset() * HeapWordSize; + InstanceKlass_vtable_start_offset = in_bytes(InstanceKlass::vtable_start_offset()); + InstanceKlass_vtable_length_offset = in_bytes(InstanceKlass::vtable_length_offset()); Method_extra_stack_entries = Method::extra_stack_entries(); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 35eb8ed0486..e6b0d8e3f40 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -949,10 +949,10 @@ public: virtual void collect_statistics(KlassSizeStats *sz) const; #endif - static int vtable_start_offset() { return header_size(); } - static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } + static ByteSize vtable_start_offset() { return in_ByteSize(header_size() * wordSize); } + static ByteSize vtable_length_offset() { return byte_offset_of(InstanceKlass, _vtable_len); } - intptr_t* start_of_vtable() const { return ((intptr_t*)this) + vtable_start_offset(); } + intptr_t* start_of_vtable() const { return (intptr_t*) ((address)this + in_bytes(vtable_start_offset())); } intptr_t* start_of_itable() const { return start_of_vtable() + vtable_length(); } int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; } diff --git a/hotspot/src/share/vm/oops/klassVtable.hpp b/hotspot/src/share/vm/oops/klassVtable.hpp index d135b33ccd2..4127a1961eb 100644 --- a/hotspot/src/share/vm/oops/klassVtable.hpp +++ b/hotspot/src/share/vm/oops/klassVtable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,6 +173,9 @@ class vtableEntry VALUE_OBJ_CLASS_SPEC { static int size() { return sizeof(vtableEntry) / sizeof(HeapWord); } + static int size_in_bytes() { + return sizeof(vtableEntry); + } static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); } Method* method() const { return _method; } diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 5bcd0b06623..cff1027c35d 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3828,8 +3828,8 @@ Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "bad index %d", vtable_index); // Get the Method* out of the appropriate vtable entry. - int entry_offset = (InstanceKlass::vtable_start_offset() + - vtable_index*vtableEntry::size()) * wordSize + + int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + + vtable_index*vtableEntry::size_in_bytes() + vtableEntry::method_offset_in_bytes(); Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); Node* target_call = make_load(NULL, entry_addr, TypePtr::NOTNULL, T_ADDRESS, MemNode::unordered); diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp index 243183c077e..8072eaa1c56 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1143,8 +1143,8 @@ Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver, builder()->CreateArrayAddress( klass, SharkType::Method_type(), - vtableEntry::size() * wordSize, - in_ByteSize(InstanceKlass::vtable_start_offset() * wordSize), + vtableEntry::size_in_bytes(), + InstanceKlass::vtable_start_offset(), LLVMValue::intptr_constant(vtable_index)), "callee"); } @@ -1166,12 +1166,12 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, Value *vtable_start = builder()->CreateAdd( builder()->CreatePtrToInt(object_klass, SharkType::intptr_type()), LLVMValue::intptr_constant( - InstanceKlass::vtable_start_offset() * HeapWordSize), + in_bytes(InstanceKlass::vtable_start_offset())), "vtable_start"); Value *vtable_length = builder()->CreateValueOfStructEntry( object_klass, - in_ByteSize(InstanceKlass::vtable_length_offset() * HeapWordSize), + InstanceKlass::vtable_length_offset(), SharkType::jint_type(), "vtable_length"); vtable_length = @@ -1182,7 +1182,7 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, vtable_start, builder()->CreateShl( vtable_length, - LLVMValue::intptr_constant(exact_log2(vtableEntry::size() * wordSize))), + LLVMValue::intptr_constant(exact_log2(vtableEntry::size_in_bytes()))), needs_aligning ? "" : "itable_start"); if (needs_aligning) { itable_start = builder()->CreateAnd( From afc61182cc62a13c620424882fa14dde8e938c2d Mon Sep 17 00:00:00 2001 From: David Lindholm Date: Wed, 27 Jan 2016 16:12:05 +0100 Subject: [PATCH 012/139] 8147940: Test gc/g1/TestG1TraceEagerReclaimHumongousObjects.java fails Reviewed-by: mgerdin, jwilhelm --- ...stG1TraceEagerReclaimHumongousObjects.java | 43 +------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java b/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java index 6ce8613468e..a4a17be430c 100644 --- a/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java +++ b/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,34 +38,6 @@ import java.util.LinkedList; public class TestG1TraceEagerReclaimHumongousObjects { public static void main(String[] args) throws Exception { - testGCLogs(); - testHumongousObjectGCLogs(); - } - - private static void testGCLogs() throws Exception { - - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", - "-Xms128M", - "-Xmx128M", - "-Xmn16M", - "-XX:G1HeapRegionSize=1M", - "-Xlog:gc+phases=trace", - "-XX:+UnlockExperimentalVMOptions", - GCTest.class.getName()); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - // As G1EagerReclaimHumongousObjects is set(default), below logs should be displayed. - // And GCTest doesn't have humongous objects, so values should be zero. - output.shouldContain("Humongous Reclaim"); - output.shouldContain("Humongous Total: 0"); - output.shouldContain("Humongous Candidate: 0"); - output.shouldContain("Humongous Reclaimed: 0"); - - output.shouldHaveExitValue(0); - } - - private static void testHumongousObjectGCLogs() throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", "-Xms128M", "-Xmx128M", @@ -90,19 +62,6 @@ public class TestG1TraceEagerReclaimHumongousObjects { output.shouldHaveExitValue(0); } - static class GCTest { - private static byte[] garbage; - - public static void main(String [] args) { - System.out.println("Creating garbage"); - // create 128MB of garbage. This should result in at least one GC - for (int i = 0; i < 1024; i++) { - garbage = new byte[128 * 1024]; - } - System.out.println("Done"); - } - } - static class GCWithHumongousObjectTest { public static final int M = 1024*1024; From 6b3dc2210dd65ad30d19cab0232ca9f43c703d77 Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Wed, 27 Jan 2016 18:22:25 +0300 Subject: [PATCH 013/139] 8141278: New tests for PLAB testing Reviewed-by: tschatzl --- .../test/gc/g1/plab/TestPLABPromotion.java | 327 ++++++++++++++++++ hotspot/test/gc/g1/plab/TestPLABResize.java | 222 ++++++++++++ .../test/gc/g1/plab/lib/AppPLABPromotion.java | 85 +++++ .../test/gc/g1/plab/lib/AppPLABResize.java | 106 ++++++ hotspot/test/gc/g1/plab/lib/LogParser.java | 142 ++++++++ .../test/gc/g1/plab/lib/MemoryConsumer.java | 86 +++++ hotspot/test/gc/g1/plab/lib/PLABUtils.java | 83 +++++ 7 files changed, 1051 insertions(+) create mode 100644 hotspot/test/gc/g1/plab/TestPLABPromotion.java create mode 100644 hotspot/test/gc/g1/plab/TestPLABResize.java create mode 100644 hotspot/test/gc/g1/plab/lib/AppPLABPromotion.java create mode 100644 hotspot/test/gc/g1/plab/lib/AppPLABResize.java create mode 100644 hotspot/test/gc/g1/plab/lib/LogParser.java create mode 100644 hotspot/test/gc/g1/plab/lib/MemoryConsumer.java create mode 100644 hotspot/test/gc/g1/plab/lib/PLABUtils.java diff --git a/hotspot/test/gc/g1/plab/TestPLABPromotion.java b/hotspot/test/gc/g1/plab/TestPLABPromotion.java new file mode 100644 index 00000000000..a2cddb8e768 --- /dev/null +++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 TestPLABPromotion + * @bug 8141278 + * @summary Test PLAB promotion + * @requires vm.gc=="G1" | vm.gc=="null" + * @library /testlibrary /../../test/lib / + * @modules java.management + * @build ClassFileInstaller + * sun.hotspot.WhiteBox + * gc.g1.plab.lib.MemoryConsumer + * gc.g1.plab.lib.LogParser + * gc.g1.plab.lib.AppPLABPromotion + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main gc.g1.plab.TestPLABPromotion + */ +package gc.g1.plab; + +import java.util.List; +import java.util.Map; +import java.util.Arrays; +import java.io.PrintStream; + +import gc.g1.plab.lib.AppPLABPromotion; +import gc.g1.plab.lib.LogParser; +import gc.g1.plab.lib.PLABUtils; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.Platform; + +/** + * Test checks PLAB promotion of different size objects. + */ +public class TestPLABPromotion { + + // GC ID with survivor PLAB statistics + private final static long GC_ID_SURVIVOR_STATS = 1l; + // GC ID with old PLAB statistics + private final static long GC_ID_OLD_STATS = 2l; + + // Threshold to determine whether the correct amount of objects were promoted. + // This is only an approximate threshold for these checks. + private final static long MEM_CONSUMPTION_THRESHOLD = 256l * 1024l; + + private static final int PLAB_SIZE_SMALL = 1024; + private static final int PLAB_SIZE_MEDIUM = 4096; + private static final int PLAB_SIZE_HIGH = 65536; + private static final int OBJECT_SIZE_SMALL = 10; + private static final int OBJECT_SIZE_MEDIUM = 100; + private static final int OBJECT_SIZE_HIGH = 1000; + private static final int GC_NUM_SMALL = 1; + private static final int GC_NUM_MEDIUM = 3; + private static final int GC_NUM_HIGH = 7; + private static final int WASTE_PCT_SMALL = 10; + private static final int WASTE_PCT_MEDIUM = 20; + private static final int WASTE_PCT_HIGH = 30; + private static final int YOUNG_SIZE_LOW = 16; + private static final int YOUNG_SIZE_HIGH = 64; + private static final boolean PLAB_FIXED = true; + private static final boolean PLAB_DYNAMIC = false; + + private final static TestCase[] TEST_CASES = { + // Test cases for unreachable object, PLAB size is fixed + new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, false, false), + new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, false, false), + // Test cases for reachable objects, PLAB size is fixed + new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_MEDIUM, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, false), + new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_SMALL, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true), + new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_HIGH, PLAB_FIXED, true, false), + // Test cases for unreachable object, PLAB size is not fixed + new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_LOW, PLAB_DYNAMIC, false, false), + // Test cases for reachable objects, PLAB size is not fixed + new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, true), + new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true), + new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, false), + new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true), + new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, true), + new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true) + }; + + public static void main(String[] args) throws Throwable { + + for (TestCase testCase : TEST_CASES) { + // What we going to check. + testCase.print(System.out); + List options = PLABUtils.prepareOptions(testCase.toOptions()); + options.add(AppPLABPromotion.class.getName()); + OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()])); + if (out.getExitValue() != 0) { + System.out.println(out.getOutput()); + throw new RuntimeException("Expect exit code 0."); + } + checkResults(out.getOutput(), testCase); + } + } + + private static void checkResults(String output, TestCase testCase) { + long plabAllocatedSurvivor; + long directAllocatedSurvivor; + long plabAllocatedOld; + long directAllocatedOld; + long memAllocated = testCase.getMemToFill(); + long wordSize = Platform.is32bit() ? 4l : 8l; + LogParser logParser = new LogParser(output); + + Map survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS); + Map oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS); + + plabAllocatedSurvivor = wordSize * survivorStats.get("used"); + directAllocatedSurvivor = wordSize * survivorStats.get("direct_allocated"); + plabAllocatedOld = wordSize * oldStats.get("used"); + directAllocatedOld = wordSize * oldStats.get("direct_allocated"); + + System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated); + System.out.printf("Old PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated); + + // Unreachable objects case + if (testCase.isDeadObjectCase()) { + // No dead objects should be promoted + if (plabAllocatedSurvivor > MEM_CONSUMPTION_THRESHOLD || directAllocatedSurvivor > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Survivor"); + } + if (plabAllocatedOld > MEM_CONSUMPTION_THRESHOLD || directAllocatedOld > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Old"); + } + } else { + // Live objects case + if (testCase.isPromotedByPLAB()) { + // All live small objects should be promoted using PLAB + if (Math.abs(plabAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Expect that Survivor PLAB allocation are similar to all mem consumed"); + } + if (Math.abs(plabAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Expect that Old PLAB allocation are similar to all mem consumed"); + } + } else { + // All big objects should be directly allocated + if (Math.abs(directAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Test fails. Expect that Survivor direct allocation are similar to all mem consumed"); + } + if (Math.abs(directAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Test fails. Expect that Old direct allocation are similar to all mem consumed"); + } + } + + // All promoted objects size should be similar to all consumed memory + if (Math.abs(plabAllocatedSurvivor + directAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Test fails. Expect that Survivor gen total allocation are similar to all mem consumed"); + } + if (Math.abs(plabAllocatedOld + directAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + System.out.println(output); + throw new RuntimeException("Test fails. Expect that Old gen total allocation are similar to all mem consumed"); + } + } + System.out.println("Test passed!"); + } + + private static Map getPlabStats(LogParser logParser, LogParser.ReportType type, long gc_id) { + + Map survivorStats = logParser.getEntries() + .get(gc_id) + .get(type); + return survivorStats; + } + + /** + * Description of one test case. + */ + private static class TestCase { + + private final int wastePct; + private final int plabSize; + private final int chunkSize; + private final int parGCThreads; + private final int edenSize; + private final boolean plabIsFixed; + private final boolean objectsAreReachable; + private final boolean promotedByPLAB; + + /** + * @param wastePct + * ParallelGCBufferWastePct + * @param plabSize + * -XX:OldPLABSize and -XX:YoungPLABSize + * @param chunkSize + * requested object size for memory consumption + * @param parGCThreads + * -XX:ParallelGCThreads + * @param edenSize + * NewSize and MaxNewSize + * @param plabIsFixed + * Use dynamic PLAB or fixed size PLAB + * @param objectsAreReachable + * true - allocate live objects + * false - allocate unreachable objects + * @param promotedByPLAB + * true - we expect to see PLAB allocation during promotion + * false - objects will be directly allocated during promotion + */ + public TestCase(int wastePct, + int plabSize, + int chunkSize, + int parGCThreads, + int edenSize, + boolean plabIsFixed, + boolean objectsAreReachable, + boolean promotedByPLAB + ) { + if (wastePct == 0 || plabSize == 0 || chunkSize == 0 || parGCThreads == 0 || edenSize == 0) { + throw new IllegalArgumentException("Parameters should not be 0"); + } + this.wastePct = wastePct; + this.plabSize = plabSize; + this.chunkSize = chunkSize; + this.parGCThreads = parGCThreads; + this.edenSize = edenSize; + this.plabIsFixed = plabIsFixed; + this.objectsAreReachable = objectsAreReachable; + this.promotedByPLAB = promotedByPLAB; + } + + /** + * Convert current TestCase to List of options. + * Assume test will fill half of existed eden. + * + * @return + * List of options + */ + public List toOptions() { + return Arrays.asList("-XX:ParallelGCThreads=" + parGCThreads, + "-XX:ParallelGCBufferWastePct=" + wastePct, + "-XX:OldPLABSize=" + plabSize, + "-XX:YoungPLABSize=" + plabSize, + "-XX:" + (plabIsFixed ? "-" : "+") + "ResizePLAB", + "-Dchunk.size=" + chunkSize, + "-Dreachable=" + objectsAreReachable, + "-XX:NewSize=" + edenSize + "m", + "-XX:MaxNewSize=" + edenSize + "m", + "-Dmem.to.fill=" + getMemToFill() + ); + } + + /** + * Print details about test case. + */ + public void print(PrintStream out) { + boolean expectPLABAllocation = promotedByPLAB && objectsAreReachable; + boolean expectDirectAllocation = (!promotedByPLAB) && objectsAreReachable; + + out.println("Test case details:"); + out.println(" Young gen size : " + edenSize + "M"); + out.println(" Predefined PLAB size : " + plabSize); + out.println(" Parallel GC buffer waste pct : " + wastePct); + out.println(" Chunk size : " + chunkSize); + out.println(" Parallel GC threads : " + parGCThreads); + out.println(" Objects are created : " + (objectsAreReachable ? "reachable" : "unreachable")); + out.println(" PLAB size is fixed: " + (plabIsFixed ? "yes" : "no")); + out.println("Test expectations:"); + out.println(" PLAB allocation : " + (expectPLABAllocation ? "expected" : "unexpected")); + out.println(" Direct allocation : " + (expectDirectAllocation ? "expected" : "unexpected")); + } + + /** + * @return + * true if we expect PLAB allocation + * false if no + */ + public boolean isPromotedByPLAB() { + return promotedByPLAB; + } + + /** + * @return + * true if it is test case for unreachable objects + * false for live objects + */ + public boolean isDeadObjectCase() { + return !objectsAreReachable; + } + + /** + * Returns amount of memory to fill + * + * @return amount of memory + */ + public long getMemToFill() { + return (long) (edenSize) * 1024l * 1024l / 2; + } + } +} diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java new file mode 100644 index 00000000000..18aef6a949b --- /dev/null +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 TestPLABResize + * @bug 8141278 + * @summary Test for PLAB resizing + * @requires vm.gc=="G1" | vm.gc=="null" + * @library /testlibrary /../../test/lib / + * @modules java.management + * @build ClassFileInstaller + * sun.hotspot.WhiteBox + * gc.g1.plab.lib.LogParser + * gc.g1.plab.lib.MemoryConsumer + * gc.g1.plab.lib.PLABUtils + * gc.g1.plab.lib.AppPLABResize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main gc.g1.plab.TestPLABResize + */ +package gc.g1.plab; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.PrintStream; + +import gc.g1.plab.lib.LogParser; +import gc.g1.plab.lib.PLABUtils; +import gc.g1.plab.lib.AppPLABResize; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +/** + * Test for PLAB resizing. + */ +public class TestPLABResize { + + private static final int OBJECT_SIZE_SMALL = 10; + private static final int OBJECT_SIZE_MEDIUM = 70; + private static final int OBJECT_SIZE_HIGH = 150; + private static final int GC_NUM_SMALL = 1; + private static final int GC_NUM_MEDIUM = 3; + private static final int GC_NUM_HIGH = 7; + private static final int WASTE_PCT_SMALL = 10; + private static final int WASTE_PCT_MEDIUM = 20; + private static final int WASTE_PCT_HIGH = 30; + + private static final int ITERATIONS_SMALL = 3; + private static final int ITERATIONS_MEDIUM = 5; + private static final int ITERATIONS_HIGH = 8; + + private final static TestCase[] TEST_CASES = { + new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_SMALL, GC_NUM_SMALL, ITERATIONS_MEDIUM), + new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_HIGH, ITERATIONS_SMALL), + new TestCase(WASTE_PCT_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, ITERATIONS_HIGH), + new TestCase(WASTE_PCT_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_HIGH, ITERATIONS_MEDIUM), + new TestCase(WASTE_PCT_MEDIUM, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, ITERATIONS_SMALL), + new TestCase(WASTE_PCT_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, ITERATIONS_HIGH), + new TestCase(WASTE_PCT_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, ITERATIONS_MEDIUM), + new TestCase(WASTE_PCT_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, ITERATIONS_SMALL), + new TestCase(WASTE_PCT_HIGH, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, ITERATIONS_HIGH) + }; + + public static void main(String[] args) throws Throwable { + for (TestCase testCase : TEST_CASES) { + testCase.print(System.out); + List options = PLABUtils.prepareOptions(testCase.toOptions()); + options.add(AppPLABResize.class.getName()); + OutputAnalyzer out = ProcessTools.executeTestJvm(options.toArray(new String[options.size()])); + if (out.getExitValue() != 0) { + System.out.println(out.getOutput()); + throw new RuntimeException("Exit code is not 0"); + } + checkResults(out.getOutput(), testCase); + } + } + + /** + * Checks testing results. + * Expected results - desired PLAB size is decreased and increased during promotion to Survivor. + * + * @param output - VM output + * @param testCase + */ + private static void checkResults(String output, TestCase testCase) { + final LogParser log = new LogParser(output); + final Map>> entries = log.getEntries(); + + final ArrayList plabSizes = entries.entrySet() + .stream() + .map(item -> { + return item.getValue() + .get(LogParser.ReportType.SURVIVOR_STATS) + .get("desired_plab_sz"); + }) + .collect(Collectors.toCollection(ArrayList::new)); + + // Check that desired plab size was changed during iterations. + // It should decrease during first half of iterations + // and increase after. + List decreasedPlabs = plabSizes.subList(testCase.getIterations(), testCase.getIterations() * 2); + List increasedPlabs = plabSizes.subList(testCase.getIterations() * 2, testCase.getIterations() * 3); + + Long prev = decreasedPlabs.get(0); + for (int index = 1; index < decreasedPlabs.size(); ++index) { + Long current = decreasedPlabs.get(index); + if (prev < current) { + System.out.println(output); + throw new RuntimeException("Test failed! Expect that previous PLAB size should be greater than current. Prev.size: " + prev + " Current size:" + current); + } + prev = current; + } + + prev = increasedPlabs.get(0); + for (int index = 1; index < increasedPlabs.size(); ++index) { + Long current = increasedPlabs.get(index); + if (prev > current) { + System.out.println(output); + throw new RuntimeException("Test failed! Expect that previous PLAB size should be less than current. Prev.size: " + prev + " Current size:" + current); + } + prev = current; + } + + System.out.println("Test passed!"); + } + + /** + * Description of one test case. + */ + private static class TestCase { + + private final int wastePct; + private final int chunkSize; + private final int parGCThreads; + private final int iterations; + + /** + * @param wastePct + * ParallelGCBufferWastePct + * @param chunkSize + * requested object size for memory consumption + * @param parGCThreads + * -XX:ParallelGCThreads + * @param iterations + * + */ + public TestCase(int wastePct, + int chunkSize, + int parGCThreads, + int iterations + ) { + if (wastePct == 0 || chunkSize == 0 || parGCThreads == 0 || iterations == 0) { + throw new IllegalArgumentException("Parameters should not be 0"); + } + this.wastePct = wastePct; + + this.chunkSize = chunkSize; + this.parGCThreads = parGCThreads; + this.iterations = iterations; + } + + /** + * Convert current TestCase to List of options. + * + * @return + * List of options + */ + public List toOptions() { + return Arrays.asList("-XX:ParallelGCThreads=" + parGCThreads, + "-XX:ParallelGCBufferWastePct=" + wastePct, + "-XX:+ResizePLAB", + "-Dthreads=" + parGCThreads, + "-Dchunk.size=" + chunkSize, + "-Diterations=" + iterations, + "-XX:NewSize=16m", + "-XX:MaxNewSize=16m" + ); + } + + /** + * Print details about test case. + */ + public void print(PrintStream out) { + out.println("Test case details:"); + out.println(" Parallel GC buffer waste pct : " + wastePct); + out.println(" Chunk size : " + chunkSize); + out.println(" Parallel GC threads : " + parGCThreads); + out.println(" Iterations: " + iterations); + } + + /** + * @return iterations + */ + public int getIterations() { + return iterations; + } + } +} diff --git a/hotspot/test/gc/g1/plab/lib/AppPLABPromotion.java b/hotspot/test/gc/g1/plab/lib/AppPLABPromotion.java new file mode 100644 index 00000000000..55fe053f368 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/AppPLABPromotion.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.plab.lib; + +import sun.hotspot.WhiteBox; + +/** + * This application is part of PLAB promotion test. + * The application fills a part of young gen with a number of small objects. + * Then it calls young GC twice to promote objects from eden to survivor, and from survivor to old. + * The test which running the application is responsible to set up test parameters + * and VM flags including flags turning GC logging on. The test will then check the produced log. + */ +final public class AppPLABPromotion { + + private final static WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + /** + * AppPLABPromotion is used for testing PLAB promotion. + * Expects the following properties to be set: + * - chunk.size - size of one object (byte array) + * - mem.to.fill - amount of memory to be consumed + * - reachable - memory should be consumed by live or dead objects + * + * @param args + */ + public static void main(String[] args) { + long chunkSize = Long.getLong("chunk.size"); + long memToFill = Long.getLong("mem.to.fill"); + boolean reachable = Boolean.getBoolean("reachable"); + if (chunkSize == 0) { + throw new IllegalArgumentException("Chunk size must be not 0"); + } + if (memToFill <= 0) { + throw new IllegalArgumentException("mem.to.fill property should be above 0"); + } + // Fill requested amount of memory + allocate(reachable, memToFill, chunkSize); + // Promote all allocated objects from Eden to Survivor + WHITE_BOX.youngGC(); + // Promote all allocated objects from Survivor to Old + WHITE_BOX.youngGC(); + } + + /** + * + * @param reachable - should allocate reachable object + * @param memSize - Memory to fill + * @param chunkSize - requested bytes per objects. + * Actual size of bytes per object will be greater + */ + private static void allocate(boolean reachable, long memSize, long chunkSize) { + long realSize = WHITE_BOX.getObjectSize(new byte[(int) chunkSize]); + int items = (int) ((memSize - 1) / (realSize)) + 1; + MemoryConsumer storage; + if (reachable) { + storage = new MemoryConsumer(items, (int) chunkSize); + } else { + storage = new MemoryConsumer(1, (int) chunkSize); + } + // Make all young gen available. + WHITE_BOX.fullGC(); + storage.consume(items * chunkSize); + } +} diff --git a/hotspot/test/gc/g1/plab/lib/AppPLABResize.java b/hotspot/test/gc/g1/plab/lib/AppPLABResize.java new file mode 100644 index 00000000000..58bbe5c8a25 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/AppPLABResize.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.plab.lib; + +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; + +/** + * This application is part of PLAB Resize test. + * The application allocates objects in 3 iterations: + * 1. Objects of fixed size + * 2. Objects of decreasing size + * 3. Objects of increasing size + * The application doesn't have any assumptions about expected behavior. + * It's supposed to be executed by a test which should set up test parameters (object sizes, number of allocations, etc) + * and VM flags including flags turning GC logging on. The test will then check the produced log. + * + * Expects the following properties to be set: + * - iterations - amount of iteration per cycle. + * - chunk.size - size of objects to be allocated + * - threads - number of gc threads (-XX:ParallelGCThreads) to calculate PLAB sizes. + */ +final public class AppPLABResize { + + // Memory to be promoted by PLAB for one thread. + private static final long MEM_ALLOC_WORDS = 32768; + // Defined by properties. + private static final int ITERATIONS = Integer.getInteger("iterations"); + private static final long CHUNK = Long.getLong("chunk.size"); + private static final int GC_THREADS = Integer.getInteger("threads"); + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + /** + * Main method for AppPLABResizing. Application expect for next properties: + * iterations, chunk.size and threads. + * + * @param args + */ + public static void main(String[] args) { + + if (ITERATIONS == 0 || CHUNK == 0 || GC_THREADS == 0) { + throw new IllegalArgumentException("Properties should be set"); + } + + long wordSize = Platform.is32bit() ? 4l : 8l; + // PLAB size is shared between threads. + long initialMemorySize = wordSize * GC_THREADS * MEM_ALLOC_WORDS; + + // Expect changing memory to half during all iterations. + long memChangeStep = initialMemorySize / 2 / ITERATIONS; + + WHITE_BOX.fullGC(); + + // Warm the PLAB. Fill memory ITERATIONS times without changing memory size. + iterateAllocation(initialMemorySize, 0); + // Fill memory ITERATIONS times. + // Initial size is initialMemorySize and step is -memChangeStep + iterateAllocation(initialMemorySize, -memChangeStep); + // Fill memory ITERATIONS times. + // Initial size is memoryAfterChanging, step is memChangeStep. + // Memory size at start should be greater then last size on previous step. + // Last size on previous step is initialMemorySize - memChangeStep*(ITERATIONS - 1) + long memoryAfterChanging = initialMemorySize - memChangeStep * (ITERATIONS - 2); + iterateAllocation(memoryAfterChanging, memChangeStep); + } + + private static void iterateAllocation(long memoryToFill, long change) { + int items; + if (change > 0) { + items = (int) ((memoryToFill + change * ITERATIONS) / CHUNK) + 1; + } else { + items = (int) (memoryToFill / CHUNK) + 1; + } + + long currentMemToFill = memoryToFill; + for (int iteration = 0; iteration < ITERATIONS; ++iteration) { + MemoryConsumer storage = new MemoryConsumer(items, (int) CHUNK); + storage.consume(currentMemToFill); + // Promote all objects to survivor + WHITE_BOX.youngGC(); + storage.clear(); + currentMemToFill += change; + } + } +} diff --git a/hotspot/test/gc/g1/plab/lib/LogParser.java b/hotspot/test/gc/g1/plab/lib/LogParser.java new file mode 100644 index 00000000000..ce2f94ef6e6 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/LogParser.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.plab.lib; + +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * LogParser class parses VM output to get PLAB and ConsumptionStats values. + * + * Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like: + * + * [2,244s][info ][gc ] GC(30) Concurrent Mark abort + * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) + * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) + * [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms + * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) + * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) + * [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms + + */ +final public class LogParser { + + // Name for GC ID field in report. + public final static String GC_ID = "gc_id"; + + /** + * Type of parsed log element. + */ + public static enum ReportType { + + SURVIVOR_STATS, + OLD_STATS + } + + private final String log; + + private final Map>> reportHolder; + + // GC ID + private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)"); + // Pattern for extraction pair = + private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+"); + + /** + * Construct LogParser Object + * + * @param log - VM Output + */ + public LogParser(String log) { + if (log == null) { + throw new IllegalArgumentException("Parameter log should not be null."); + } + this.log = log; + reportHolder = parseLines(); + } + + /** + * @return log which is being processed + */ + public String getLog() { + return log; + } + + /** + * Returns list of log entries. + * + * @return list of Pair with ReportType and Map of parameters/values. + */ + public Map>> getEntries() { + return reportHolder; + } + + private Map>> parseLines() throws NumberFormatException { + Scanner lineScanner = new Scanner(log); + Map>> allocationStatistics = new HashMap<>(); + Optional gc_id; + while (lineScanner.hasNextLine()) { + String line = lineScanner.nextLine(); + gc_id = getGcId(line); + if ( gc_id.isPresent() ) { + Matcher matcher = PAIRS_PATTERN.matcher(line); + if (matcher.find()) { + Map> oneReportItem; + ReportType reportType; + // Second line in log is statistics for Old PLAB allocation + if ( !allocationStatistics.containsKey(gc_id.get()) ) { + oneReportItem = new EnumMap<>(ReportType.class); + reportType = ReportType.SURVIVOR_STATS; + allocationStatistics.put(gc_id.get(), oneReportItem); + } else { + oneReportItem = allocationStatistics.get(gc_id.get()); + reportType = ReportType.OLD_STATS; + } + + // Extract all pairs from log. + HashMap plabStats = new HashMap<>(); + do { + String pair = matcher.group(); + String[] nameValue = pair.replaceAll(" ", "").split("="); + plabStats.put(nameValue[0], Long.parseLong(nameValue[1])); + } while (matcher.find()); + oneReportItem.put(reportType,plabStats); + } + } + } + return allocationStatistics; + } + + private Optional getGcId(String line) { + Matcher number = GC_ID_PATTERN.matcher(line); + if (number.find()) { + return Optional.of(Long.parseLong(number.group(1))); + } + return Optional.empty(); + } +} diff --git a/hotspot/test/gc/g1/plab/lib/MemoryConsumer.java b/hotspot/test/gc/g1/plab/lib/MemoryConsumer.java new file mode 100644 index 00000000000..1ac78da4f52 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/MemoryConsumer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.plab.lib; + +/** + * The MemoryConsumer is used for consuming different amount of memory. + * Class will store not more than 'capacity' number of objects with 'chunk' size. + * If we exceed capacity, object will be stored at existing entries, + * all previously added objects will be overwritten. + * If capacity=1, only last object will be saved. + */ +public class MemoryConsumer { + + private int capacity; + private int chunk; + + private Object[] array; + private int index; + + /** + * Create MemoryConsumer object with defined capacity + * + * @param capacity + * @param chunk + */ + public MemoryConsumer(int capacity, int chunk) { + if (capacity <= 0) { + throw new IllegalArgumentException("Items number should be greater than 0."); + } + if (chunk <= 0) { + throw new IllegalArgumentException("Chunk size should be greater than 0."); + } + this.capacity = capacity; + this.chunk = chunk; + index = 0; + array = new Object[this.capacity]; + } + + /** + * Store object into MemoryConsumer. + * + * @param o - Object to store + */ + private void store(Object o) { + if (array == null) { + throw new RuntimeException("Capacity should be set before storing"); + } + array[index % capacity] = o; + ++index; + } + + public void consume(long memoryToFill) { + long allocated = 0; + while (allocated < memoryToFill) { + store(new byte[chunk]); + allocated += chunk; + } + } + + /** + * Clear all stored objects. + */ + public void clear() { + array = null; + } +} diff --git a/hotspot/test/gc/g1/plab/lib/PLABUtils.java b/hotspot/test/gc/g1/plab/lib/PLABUtils.java new file mode 100644 index 00000000000..3c61f6b28fb --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/PLABUtils.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.plab.lib; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import jdk.test.lib.Utils; + +/** + * Utilities for PLAB testing. + */ +public class PLABUtils { + + /** + * PLAB tests default options list + */ + private final static String[] GC_TUNE_OPTIONS = { + "-XX:+UseG1GC", + "-XX:G1HeapRegionSize=1m", + "-XX:OldSize=64m", + "-XX:-UseAdaptiveSizePolicy", + "-XX:-UseTLAB", + "-XX:SurvivorRatio=1" + }; + + /** + * GC logging options list. + */ + private final static String G1_PLAB_LOGGING_OPTIONS[] = { + "-Xlog:gc=debug,gc+plab=debug" + }; + + /** + * List of options required to use WhiteBox. + */ + private final static String WB_DIAGNOSTIC_OPTIONS[] = { + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI" + }; + + /** + * Prepares options for testing. + * + * @param options - additional options for testing + * @return List of options + */ + public static List prepareOptions(List options) { + if (options == null) { + throw new IllegalArgumentException("Options cannot be null"); + } + List executionOtions = new ArrayList<>( + Arrays.asList(Utils.getTestJavaOpts()) + ); + Collections.addAll(executionOtions, WB_DIAGNOSTIC_OPTIONS); + Collections.addAll(executionOtions, G1_PLAB_LOGGING_OPTIONS); + Collections.addAll(executionOtions, GC_TUNE_OPTIONS); + executionOtions.addAll(options); + return executionOtions; + } +} From 469ae3ecc7a0c10d2283fca4dc5d7f408e9300e7 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Wed, 27 Jan 2016 11:12:25 -0500 Subject: [PATCH 014/139] 8146137: runtime/logging/ExceptionsTest.java fails on embedded and ARM test Removed part of ExceptionsTest.java looking for exception that is not printed when function is compiled on embedded/ARM Reviewed-by: coleenp, dholmes --- .../test/runtime/logging/ExceptionsTest.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/hotspot/test/runtime/logging/ExceptionsTest.java b/hotspot/test/runtime/logging/ExceptionsTest.java index b3c637ad251..0b9886e331b 100644 --- a/hotspot/test/runtime/logging/ExceptionsTest.java +++ b/hotspot/test/runtime/logging/ExceptionsTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8141211 - * @summary exceptions=info output should have an exception message for both interpreter and compiled methods + * @summary exceptions=info output should have an exception message for interpreter methods * @library /testlibrary * @modules java.base/sun.misc * java.management @@ -40,8 +40,6 @@ public class ExceptionsTest { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain(""); output.shouldContain(" thrown in interpreter method "); - output.shouldContain(" thrown in compiled method "); - output.shouldContain("Exception 2 caught."); output.shouldHaveExitValue(0); } @@ -53,46 +51,29 @@ public class ExceptionsTest { public static void main(String[] args) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:exceptions=info", - "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", InternalClass.class.getName()); analyzeOutputOn(pb); pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceExceptions", - "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", InternalClass.class.getName()); analyzeOutputOn(pb); pb = ProcessTools.createJavaProcessBuilder("-Xlog:exceptions=off", - "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", InternalClass.class.getName()); analyzeOutputOff(pb); pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceExceptions", - "-Xcomp", - "-XX:CompileCommand=compileonly,ExceptionsTest$InternalClass::compileMe", InternalClass.class.getName()); analyzeOutputOff(pb); } public static class InternalClass { - public static void compileMe() throws Exception { - try { - throw new RuntimeException("Test exception 2 for logging"); - } catch (Exception e) { - System.out.println("Exception 2 caught."); - } - } - public static void main(String[] args) throws Exception { try { throw new RuntimeException("Test exception 1 for logging"); } catch (Exception e) { System.out.println("Exception 1 caught."); } - compileMe(); } } } From 094345fc88834131bcc13727a6159340c86ce6f5 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Wed, 27 Jan 2016 10:30:27 -0800 Subject: [PATCH 015/139] 8145192: 'count' variable can overflow in PSMarkSweep::invoke on 64 bit JVM Changed MarkSweepAlwaysCompactCount from uintx to uint Reviewed-by: tschatzl, tbenson --- hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp | 4 ++-- hotspot/src/share/vm/gc/shared/collectorPolicy.cpp | 4 ++-- hotspot/src/share/vm/runtime/globals.hpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp index 4b8bcf77c71..5b93e8a78ca 100644 --- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,7 +99,7 @@ void PSMarkSweep::invoke(bool maximum_heap_compaction) { heap->collector_policy()->should_clear_all_soft_refs(); uint count = maximum_heap_compaction ? 1 : MarkSweepAlwaysCompactCount; - UIntXFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count); + UIntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count); PSMarkSweep::invoke_no_policy(clear_all_soft_refs || maximum_heap_compaction); } diff --git a/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp b/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp index fa1e2eaddbc..bdfe9688818 100644 --- a/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -774,7 +774,7 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, // free memory should be here, especially if they are expensive. If this // attempt fails, an OOM exception will be thrown. { - UIntXFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted + UIntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted gch->do_collection(true, // full true, // clear_all_soft_refs diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index c3df46be9b2..9bc40f4e34a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3395,10 +3395,10 @@ public: "also has a smaller default value; see arguments.cpp.") \ range(0, 100) \ \ - product(uintx, MarkSweepAlwaysCompactCount, 4, \ + product(uint, MarkSweepAlwaysCompactCount, 4, \ "How often should we fully compact the heap (ignoring the dead " \ "space parameters)") \ - range(1, max_uintx) \ + range(1, max_juint) \ \ develop(uintx, GCExpandToAllocateDelayMillis, 0, \ "Delay between expansion and allocation (in milliseconds)") \ From 0a7cee219017d60184edc004cb3bf62ffe7c52e1 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Wed, 27 Jan 2016 22:39:03 -0500 Subject: [PATCH 016/139] 8147500: The HashtableTextDump::get_num() should check for integer overflow Add check for integer overflow in HashtableTextDump::get_num() Reviewed-by: dholmes, iklam --- .../share/vm/classfile/compactHashtable.cpp | 14 ++++++------- .../share/vm/classfile/compactHashtable.hpp | 21 +++++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/classfile/compactHashtable.cpp b/hotspot/src/share/vm/classfile/compactHashtable.cpp index 68781c1e14d..a2c507d3078 100644 --- a/hotspot/src/share/vm/classfile/compactHashtable.cpp +++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp @@ -365,14 +365,14 @@ bool HashtableTextDump::skip_newline() { } int HashtableTextDump::skip(char must_be_char) { - corrupted_if(remain() < 1); - corrupted_if(*_p++ != must_be_char); + corrupted_if(remain() < 1, "Truncated"); + corrupted_if(*_p++ != must_be_char, "Unexpected character"); return 0; } void HashtableTextDump::skip_past(char c) { for (;;) { - corrupted_if(remain() < 1); + corrupted_if(remain() < 1, "Truncated"); if (*_p++ == c) { return; } @@ -381,7 +381,7 @@ void HashtableTextDump::skip_past(char c) { void HashtableTextDump::check_version(const char* ver) { int len = (int)strlen(ver); - corrupted_if(remain() < len); + corrupted_if(remain() < len, "Truncated"); if (strncmp(_p, ver, len) != 0) { quit("wrong version of hashtable dump file", _filename); } @@ -451,7 +451,7 @@ int HashtableTextDump::scan_symbol_prefix() { jchar HashtableTextDump::unescape(const char* from, const char* end, int count) { jchar value = 0; - corrupted_if(from + count > end); + corrupted_if(from + count > end, "Truncated"); for (int i=0; i end); + corrupted_if(from + 2 > end, "Truncated"); char c = from[1]; from += 2; switch (c) { @@ -507,7 +507,7 @@ void HashtableTextDump::get_utf8(char* utf8_buffer, int utf8_length) { } } } - corrupted_if(n > 0); // expected more chars but file has ended + corrupted_if(n > 0, "Truncated"); // expected more chars but file has ended _p = from; skip_newline(); } diff --git a/hotspot/src/share/vm/classfile/compactHashtable.hpp b/hotspot/src/share/vm/classfile/compactHashtable.hpp index 1c9e336729a..ea602229d94 100644 --- a/hotspot/src/share/vm/classfile/compactHashtable.hpp +++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp @@ -276,9 +276,9 @@ public: void corrupted(const char *p, const char *msg); - inline void corrupted_if(bool cond) { + inline void corrupted_if(bool cond, const char *msg) { if (cond) { - corrupted(_p, NULL); + corrupted(_p, msg); } } @@ -287,27 +287,30 @@ public: void skip_past(char c); void check_version(const char* ver); - inline bool get_num(char delim, int *utf8_length) { + inline void get_num(char delim, int *num) { const char* p = _p; const char* end = _end; - int num = 0; + u8 n = 0; while (p < end) { char c = *p ++; if ('0' <= c && c <= '9') { - num = num * 10 + (c - '0'); + n = n * 10 + (c - '0'); + if (n > (u8)INT_MAX) { + corrupted(_p, "Num overflow"); + } } else if (c == delim) { _p = p; - *utf8_length = num; - return true; + *num = (int)n; + return; } else { // Not [0-9], not 'delim' - return false; + corrupted(_p, "Unrecognized format");; } } + corrupted(_end, "Incorrect format"); ShouldNotReachHere(); - return false; } void scan_prefix_type(); From 31ca2b7010821c81c48f66b009faaa2cd95a07ff Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Thu, 28 Jan 2016 10:04:35 +0100 Subject: [PATCH 017/139] 8145180: Add back PrintGC, PrintGCDetails and -Xloggc Reviewed-by: sjohanss, david --- hotspot/src/share/vm/runtime/arguments.cpp | 27 +++++ hotspot/src/share/vm/runtime/arguments.hpp | 3 + hotspot/src/share/vm/runtime/globals.hpp | 8 ++ .../gc/logging/TestDeprecatedPrintFlags.java | 108 ++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 hotspot/test/gc/logging/TestDeprecatedPrintFlags.java diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 365013e152d..5134ab58ff8 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -83,6 +83,7 @@ char** Arguments::_jvm_args_array = NULL; int Arguments::_num_jvm_args = 0; char* Arguments::_java_command = NULL; SystemProperty* Arguments::_system_properties = NULL; +const char* Arguments::_gc_log_filename = NULL; bool Arguments::_has_profile = false; size_t Arguments::_conservative_max_heap_alignment = 0; size_t Arguments::_min_heap_size = 0; @@ -3090,6 +3091,10 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // -Xnoagent } else if (match_option(option, "-Xnoagent")) { // For compatibility with classic. HotSpot refuses to load the old style agent.dll. + } else if (match_option(option, "-Xloggc:", &tail)) { + // Deprecated flag to redirect GC output to a file. -Xloggc: + log_warning(gc)("-Xloggc is deprecated. Will use -Xlog:gc:%s instead.", tail); + _gc_log_filename = os::strdup_check_oom(tail); } else if (match_option(option, "-Xlog", &tail)) { bool ret = false; if (strcmp(tail, ":help") == 0) { @@ -3999,6 +4004,24 @@ static void print_options(const JavaVMInitArgs *args) { } } +bool Arguments::handle_deprecated_print_gc_flags() { + if (PrintGC) { + log_warning(gc)("-XX:+PrintGC is deprecated. Will use -Xlog:gc instead."); + } + if (PrintGCDetails) { + log_warning(gc)("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); + } + + if (_gc_log_filename != NULL) { + // -Xloggc was used to specify a filename + const char* gc_conf = PrintGCDetails ? "gc*" : "gc"; + return LogConfiguration::parse_log_arguments(_gc_log_filename, gc_conf, NULL, NULL, NULL); + } else if (PrintGC || PrintGCDetails) { + LogConfiguration::configure_stdout(LogLevel::Info, !PrintGCDetails, LOG_TAGS(gc)); + } + return true; +} + // Parse entry point called from JNI_CreateJavaVM jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { @@ -4147,6 +4170,10 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) { ScavengeRootsInCode = 1; } + if (!handle_deprecated_print_gc_flags()) { + return JNI_EINVAL; + } + // Set object alignment values. set_object_alignment(); diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index a6918fde8e7..e7ce4f30cab 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -294,6 +294,7 @@ class Arguments : AllStatic { // Option flags static bool _has_profile; + static const char* _gc_log_filename; // Value of the conservative maximum heap alignment needed static size_t _conservative_max_heap_alignment; @@ -400,6 +401,8 @@ class Arguments : AllStatic { static jint match_special_option_and_act(const JavaVMInitArgs* args, ScopedVMInitArgs* args_out); + static bool handle_deprecated_print_gc_flags(); + static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args, const JavaVMInitArgs *java_options_args, const JavaVMInitArgs *cmd_line_args); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 9bc40f4e34a..0c45b3b89e6 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2391,6 +2391,14 @@ public: "will sleep while yielding before giving up and resuming GC") \ range(0, max_juint) \ \ + product(bool, PrintGC, false, \ + "Print message at garbage collection. " \ + "Deprecated, use -Xlog:gc instead.") \ + \ + product(bool, PrintGCDetails, false, \ + "Print more details at garbage collection. " \ + "Deprecated, use -Xlog:gc* instead.") \ + \ develop(intx, ConcGCYieldTimeout, 0, \ "If non-zero, assert that GC threads yield within this " \ "number of milliseconds") \ diff --git a/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java b/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java new file mode 100644 index 00000000000..a9ac87a5255 --- /dev/null +++ b/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 TestDeprecatedPrintFlags + * @bug 8145180 + * @summary Verify PrintGC, PrintGCDetails and -Xloggc + * @key gc + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + */ + +import jdk.test.lib.*; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; + +public class TestDeprecatedPrintFlags { + + public static void testPrintGC() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintGC", "DoGC"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("-XX:+PrintGC is deprecated. Will use -Xlog:gc instead."); + output.shouldNotContain("PrintGCDetails"); + output.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); + output.shouldHaveExitValue(0); + } + + public static void testPrintGCDetails() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintGCDetails", "DoGC"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); + output.shouldNotContain("PrintGC is deprecated"); + output.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldMatch("\\[info.*\\]\\[gc\\,"); + output.shouldHaveExitValue(0); + } + + public static void testXloggc() throws Exception { + String fileName = "gc-test.log"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xloggc:" + fileName, "DoGC"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("-Xloggc is deprecated. Will use -Xlog:gc:gc-test.log instead."); + output.shouldNotContain("PrintGCDetails"); + output.shouldNotContain("PrintGC"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); + output.shouldHaveExitValue(0); + String lines = Files.lines(Paths.get(fileName)).collect(Collectors.joining()); + System.out.println("lines: " + lines); + OutputAnalyzer outputLog = new OutputAnalyzer(lines, ""); + outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + outputLog.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); + } + + public static void testXloggcWithPrintGCDetails() throws Exception { + String fileName = "gc-test.log"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintGCDetails", "-Xloggc:" + fileName, "DoGC"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); + output.shouldContain("-Xloggc is deprecated. Will use -Xlog:gc:gc-test.log instead."); + output.shouldNotContain("PrintGC is deprecated"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); + output.shouldHaveExitValue(0); + String lines = Files.lines(Paths.get(fileName)).collect(Collectors.joining()); + OutputAnalyzer outputLog = new OutputAnalyzer(lines, ""); + outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc\\,"); + } + + public static void main(String[] args) throws Exception { + testPrintGC(); + testPrintGCDetails(); + testXloggc(); + testXloggcWithPrintGCDetails(); + } +} + +class DoGC { + public static void main(String[] args) { + System.gc(); + } +} From 17b9e0a7aa2ff6648180f49b84bc7df389cf0770 Mon Sep 17 00:00:00 2001 From: Alexander Kulyakhtin Date: Thu, 28 Jan 2016 14:58:57 +0300 Subject: [PATCH 018/139] 8147447: serviceability/tmtools/jstack/WaitNotifyThreadTest.java test fails Corrected verification of the jstack object references Reviewed-by: sla --- .../tmtools/jstack/WaitNotifyThreadTest.java | 13 ++++++++--- .../tmtools/jstack/utils/DefaultFormat.java | 22 ++++++++++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/hotspot/test/serviceability/tmtools/jstack/WaitNotifyThreadTest.java b/hotspot/test/serviceability/tmtools/jstack/WaitNotifyThreadTest.java index 75b04597cd2..198124cf3a0 100644 --- a/hotspot/test/serviceability/tmtools/jstack/WaitNotifyThreadTest.java +++ b/hotspot/test/serviceability/tmtools/jstack/WaitNotifyThreadTest.java @@ -88,6 +88,7 @@ public class WaitNotifyThreadTest { } private void doTest() throws Exception { + // Verify stack trace consistency when notifying the thread doTest(new ActionNotify()); @@ -134,8 +135,7 @@ public class WaitNotifyThreadTest { if (mi.getName().startsWith(OBJECT_WAIT) && mi.getCompilationUnit() == null /*native method*/) { if (mi.getLocks().size() == 1) { MonitorInfo monInfo = mi.getLocks().getFirst(); - if (monInfo.getType().equals("waiting on") - && monInfo.getMonitorClass().equals(OBJECT)) { + if (monInfo.getType().equals("waiting on") && compareMonitorClass(monInfo)) { monitorAddress = monInfo.getMonitorAddress(); } else { System.err.println("Error: incorrect monitor info: " + monInfo.getType() + ", " + monInfo.getMonitorClass()); @@ -166,7 +166,7 @@ public class WaitNotifyThreadTest { private void assertMonitorInfo(String expectedMessage, MonitorInfo monInfo, String monitorAddress) { if (monInfo.getType().equals(expectedMessage) - && monInfo.getMonitorClass().equals(OBJECT + "11") + && compareMonitorClass(monInfo) && monInfo.getMonitorAddress().equals( monitorAddress)) { System.out.println("Correct monitor info found"); @@ -177,6 +177,13 @@ public class WaitNotifyThreadTest { } } + private boolean compareMonitorClass(MonitorInfo monInfo) { + // If monitor class info is present in the jstack output + // then compare it with the class of the actual monitor object + // If there is no monitor class info available then return true + return OBJECT.equals(monInfo.getMonitorClass()) || (monInfo.getMonitorClass() == null); + } + private void analyzeThreadStackNoWaiting(ThreadStack ti2) { Iterator it = ti2.getStack().iterator(); diff --git a/hotspot/test/serviceability/tmtools/jstack/utils/DefaultFormat.java b/hotspot/test/serviceability/tmtools/jstack/utils/DefaultFormat.java index 4c753a5c0c9..6ce6c1b2c80 100644 --- a/hotspot/test/serviceability/tmtools/jstack/utils/DefaultFormat.java +++ b/hotspot/test/serviceability/tmtools/jstack/utils/DefaultFormat.java @@ -70,10 +70,18 @@ public class DefaultFormat implements Format { return "^JNI\\sglobal\\sreferences:\\s((.+))$"; } + // Sample string that matches the pattern: + // waiting on <0x000000008f64e6d0> (a java.lang.Object) protected String monitorInfoPattern() { return "^\\s+\\-\\s(locked|waiting\\son|waiting\\sto\\slock)\\s\\<(.*)\\>\\s\\(((.*))\\)$"; } + // Sample string that matches the pattern: + // waiting on + protected String monitorInfoNoObjectRefPattern() { + return "^\\s+\\-\\s(locked|waiting\\son|waiting\\sto\\slock)\\s\\<(.*)\\>$"; + } + protected String vmVersionInfoPattern() { return "Full\\sthread\\sdump\\s.*"; } @@ -100,7 +108,10 @@ public class DefaultFormat implements Format { currentMethodInfo = parseMethodInfo(line); currentThreadStack.addMethod(currentMethodInfo); } else if (line.matches(monitorInfoPattern())) { - MonitorInfo mi = parseMonitorInfo(line); + MonitorInfo mi = parseMonitorInfo(line, monitorInfoPattern()); + currentMethodInfo.getLocks().add(mi); + } else if (line.matches(monitorInfoNoObjectRefPattern())) { + MonitorInfo mi = parseMonitorInfo(line, monitorInfoNoObjectRefPattern()); currentMethodInfo.getLocks().add(mi); } else if (line.matches(extendedStatusPattern())) { currentThreadStack.setExtendedStatus(parseExtendedStatus(line)); @@ -125,16 +136,17 @@ public class DefaultFormat implements Format { return result; } - private MonitorInfo parseMonitorInfo(String line) { + private MonitorInfo parseMonitorInfo(String line, String pattern) { Scanner s = new Scanner(line); - s.findInLine(monitorInfoPattern()); + s.findInLine(pattern); MonitorInfo mi = new MonitorInfo(); MatchResult res = s.match(); mi.setType(res.group(1)); mi.setMonitorAddress(res.group(2)); - mi.setMonitorClass(res.group(3)); - + if (res.groupCount() > 2) { + mi.setMonitorClass(res.group(3)); + } return mi; } From 4f42f17d9e14dd42622eab75f0488497d8353400 Mon Sep 17 00:00:00 2001 From: Ray Alex Date: Thu, 28 Jan 2016 13:30:12 +0100 Subject: [PATCH 019/139] 8146987: Improve Parallel GC Full GC by caching results of live_words_in_range() A large part of time in the parallel scavenge collector is spent finding out the amount of live words within memory ranges to find out where to move an object to. Try to incrementally calculate this value. Reviewed-by: tschatzl, mgerdin, jmasa --- .../share/vm/gc/parallel/parMarkBitMap.cpp | 52 ++++++++++- .../share/vm/gc/parallel/parMarkBitMap.hpp | 11 ++- .../vm/gc/parallel/psCompactionManager.cpp | 11 ++- .../vm/gc/parallel/psCompactionManager.hpp | 23 ++++- .../parallel/psCompactionManager.inline.hpp | 4 +- .../vm/gc/parallel/psParallelCompact.cpp | 90 ++++++++++--------- .../vm/gc/parallel/psParallelCompact.hpp | 28 +++--- .../gc/parallel/psParallelCompact.inline.hpp | 8 +- .../vm/oops/instanceClassLoaderKlass.hpp | 4 +- hotspot/src/share/vm/oops/instanceKlass.hpp | 2 +- .../src/share/vm/oops/instanceMirrorKlass.hpp | 4 +- .../src/share/vm/oops/instanceRefKlass.hpp | 4 +- hotspot/src/share/vm/oops/klass.hpp | 4 +- hotspot/src/share/vm/oops/objArrayKlass.hpp | 4 +- hotspot/src/share/vm/oops/oop.hpp | 4 +- hotspot/src/share/vm/oops/oop.inline.hpp | 4 +- hotspot/src/share/vm/oops/typeArrayKlass.hpp | 4 +- 17 files changed, 180 insertions(+), 81 deletions(-) diff --git a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp index 2965749e981..569ff9ecbb1 100644 --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/parallel/parMarkBitMap.hpp" +#include "gc/parallel/psCompactionManager.inline.hpp" #include "gc/parallel/psParallelCompact.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" @@ -96,7 +97,20 @@ ParMarkBitMap::mark_obj(HeapWord* addr, size_t size) return false; } -size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const +inline bool +ParMarkBitMap::is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const { + return cm->last_query_begin() == beg_addr; +} + +inline void +ParMarkBitMap::update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const { + cm->set_last_query_begin(beg_addr); + cm->set_last_query_object(end_obj); + cm->set_last_query_return(result); +} + +size_t +ParMarkBitMap::live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const { assert(beg_addr <= (HeapWord*)end_obj, "bad range"); assert(is_marked(end_obj), "end_obj must be live"); @@ -117,6 +131,42 @@ size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const return bits_to_words(live_bits); } +size_t +ParMarkBitMap::live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const +{ + HeapWord* last_beg = cm->last_query_begin(); + oop last_obj = cm->last_query_object(); + size_t last_ret = cm->last_query_return(); + if (end_obj > last_obj) { + last_ret = last_ret + live_words_in_range_helper((HeapWord*)last_obj, end_obj); + last_obj = end_obj; + } else if (end_obj < last_obj) { + // The cached value is for an object that is to the left (lower address) of the current + // end_obj. Calculate back from that cached value. + if (pointer_delta((HeapWord*)end_obj, (HeapWord*)beg_addr) > pointer_delta((HeapWord*)last_obj, (HeapWord*)end_obj)) { + last_ret = last_ret - live_words_in_range_helper((HeapWord*)end_obj, last_obj); + } else { + last_ret = live_words_in_range_helper(beg_addr, end_obj); + } + last_obj = end_obj; + } + + update_live_words_in_range_cache(cm, last_beg, last_obj, last_ret); + return last_ret; +} + +size_t +ParMarkBitMap::live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const +{ + // Try to reuse result from ParCompactionManager cache first. + if (is_live_words_in_range_in_cache(cm, beg_addr)) { + return live_words_in_range_use_cache(cm, beg_addr, end_obj); + } + size_t ret = live_words_in_range_helper(beg_addr, end_obj); + update_live_words_in_range_cache(cm, beg_addr, end_obj, ret); + return ret; +} + ParMarkBitMap::IterationStatus ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, idx_t range_beg, idx_t range_end) const diff --git a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp index acf2f917d59..3f29f94fc97 100644 --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ class ParMarkBitMapClosure; class PSVirtualSpace; +class ParCompactionManager; class ParMarkBitMap: public CHeapObj { @@ -124,7 +125,7 @@ public: // the range are included in the result. The end of the range must be a live object, // which is the case when updating pointers. This allows a branch to be removed // from inside the loop. - size_t live_words_in_range(HeapWord* beg_addr, oop end_obj) const; + size_t live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const; inline HeapWord* region_start() const; inline HeapWord* region_end() const; @@ -167,6 +168,12 @@ public: #endif // #ifdef ASSERT private: + size_t live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const; + + bool is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const; + size_t live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const; + void update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const; + // Each bit in the bitmap represents one unit of 'object granularity.' Objects // are double-word aligned in 32-bit VMs, but not in 64-bit VMs, so the 32-bit // granularity is 2, 64-bit is 1. diff --git a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp index 261098b0c49..433b4dc2a06 100644 --- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp +++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,6 +68,8 @@ ParCompactionManager::ParCompactionManager() : marking_stack()->initialize(); _objarray_stack.initialize(); + + reset_bitmap_query_cache(); } ParCompactionManager::~ParCompactionManager() { @@ -124,6 +126,13 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { "Not initialized?"); } +void ParCompactionManager::reset_all_bitmap_query_caches() { + uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers(); + for (uint i=0; i<=parallel_gc_threads; i++) { + _manager_array[i]->reset_bitmap_query_cache(); + } +} + int ParCompactionManager::pop_recycled_stack_index() { assert(_recycled_bottom <= _recycled_top, "list is empty"); // Get the next available index diff --git a/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp b/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp index be680ae4197..9e35ff29d9e 100644 --- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp +++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,6 +109,10 @@ private: Action _action; + HeapWord* _last_query_beg; + oop _last_query_obj; + size_t _last_query_ret; + static PSOldGen* old_gen() { return _old_gen; } static ObjectStartArray* start_array() { return _start_array; } static OopTaskQueueSet* stack_array() { return _stack_array; } @@ -127,9 +131,26 @@ private: // marking stack and overflow stack directly. public: + void reset_bitmap_query_cache() { + _last_query_beg = NULL; + _last_query_obj = NULL; + _last_query_ret = 0; + } + Action action() { return _action; } void set_action(Action v) { _action = v; } + // Bitmap query support, cache last query and result + HeapWord* last_query_begin() { return _last_query_beg; } + oop last_query_object() { return _last_query_obj; } + size_t last_query_return() { return _last_query_ret; } + + void set_last_query_begin(HeapWord *new_beg) { _last_query_beg = new_beg; } + void set_last_query_object(oop new_obj) { _last_query_obj = new_obj; } + void set_last_query_return(size_t new_ret) { _last_query_ret = new_ret; } + + static void reset_all_bitmap_query_caches(); + RegionTaskQueue* region_stack() { return _region_stack; } void set_region_stack(RegionTaskQueue* v) { _region_stack = v; } diff --git a/hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp b/hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp index 7ba99f95ede..7def8417b42 100644 --- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp +++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,7 +144,7 @@ inline void ParCompactionManager::follow_contents(objArrayOop obj, int index) { } inline void ParCompactionManager::update_contents(oop obj) { - obj->pc_update_contents(); + obj->pc_update_contents(this); } #endif // SHARE_VM_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index d26948de533..473610c1b1f 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -751,7 +751,7 @@ bool ParallelCompactData::summarize(SplitInfo& split_info, return true; } -HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr) { +HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr, ParCompactionManager* cm) { assert(addr != NULL, "Should detect NULL oop earlier"); assert(ParallelScavengeHeap::heap()->is_in(addr), "not in heap"); assert(PSParallelCompact::mark_bitmap()->is_marked(addr), "not marked"); @@ -788,7 +788,7 @@ HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr) { const size_t block_offset = addr_to_block_ptr(addr)->offset(); const ParMarkBitMap* bitmap = PSParallelCompact::mark_bitmap(); - const size_t live = bitmap->live_words_in_range(search_start, oop(addr)); + const size_t live = bitmap->live_words_in_range(cm, search_start, oop(addr)); result += block_offset + live; DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result)); return result; @@ -825,11 +825,9 @@ PSParallelCompact::IsAliveClosure PSParallelCompact::_is_alive_closure; bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); } -PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closure; -PSParallelCompact::AdjustKlassClosure PSParallelCompact::_adjust_klass_closure; - void PSParallelCompact::AdjustKlassClosure::do_klass(Klass* klass) { - klass->oops_do(&PSParallelCompact::_adjust_pointer_closure); + PSParallelCompact::AdjustPointerClosure closure(_cm); + klass->oops_do(&closure); } void PSParallelCompact::post_initialize() { @@ -977,6 +975,8 @@ void PSParallelCompact::pre_compact() // Have worker threads release resources the next time they run a task. gc_task_manager()->release_all_resources(); + + ParCompactionManager::reset_all_bitmap_query_caches(); } void PSParallelCompact::post_compact() @@ -1801,7 +1801,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { // adjust_roots() updates Universe::_intArrayKlassObj which is // needed by the compaction for filling holes in the dense prefix. - adjust_roots(); + adjust_roots(vmthread_cm); compaction_start.update(); compact(); @@ -2142,39 +2142,42 @@ public: }; static PSAlwaysTrueClosure always_true; -void PSParallelCompact::adjust_roots() { +void PSParallelCompact::adjust_roots(ParCompactionManager* cm) { // Adjust the pointers to reflect the new locations GCTraceTime(Trace, gc, phases) tm("Adjust Roots", &_gc_timer); // Need new claim bits when tracing through and adjusting pointers. ClassLoaderDataGraph::clear_claimed_marks(); + PSParallelCompact::AdjustPointerClosure oop_closure(cm); + PSParallelCompact::AdjustKlassClosure klass_closure(cm); + // General strong roots. - Universe::oops_do(adjust_pointer_closure()); - JNIHandles::oops_do(adjust_pointer_closure()); // Global (strong) JNI handles - CLDToOopClosure adjust_from_cld(adjust_pointer_closure()); - Threads::oops_do(adjust_pointer_closure(), &adjust_from_cld, NULL); - ObjectSynchronizer::oops_do(adjust_pointer_closure()); - FlatProfiler::oops_do(adjust_pointer_closure()); - Management::oops_do(adjust_pointer_closure()); - JvmtiExport::oops_do(adjust_pointer_closure()); - SystemDictionary::oops_do(adjust_pointer_closure()); - ClassLoaderDataGraph::oops_do(adjust_pointer_closure(), adjust_klass_closure(), true); + Universe::oops_do(&oop_closure); + JNIHandles::oops_do(&oop_closure); // Global (strong) JNI handles + CLDToOopClosure adjust_from_cld(&oop_closure); + Threads::oops_do(&oop_closure, &adjust_from_cld, NULL); + ObjectSynchronizer::oops_do(&oop_closure); + FlatProfiler::oops_do(&oop_closure); + Management::oops_do(&oop_closure); + JvmtiExport::oops_do(&oop_closure); + SystemDictionary::oops_do(&oop_closure); + ClassLoaderDataGraph::oops_do(&oop_closure, &klass_closure, true); // Now adjust pointers in remaining weak roots. (All of which should // have been cleared if they pointed to non-surviving objects.) // Global (weak) JNI handles - JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure()); + JNIHandles::weak_oops_do(&always_true, &oop_closure); - CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations); + CodeBlobToOopClosure adjust_from_blobs(&oop_closure, CodeBlobToOopClosure::FixRelocations); CodeCache::blobs_do(&adjust_from_blobs); - StringTable::oops_do(adjust_pointer_closure()); - ref_processor()->weak_oops_do(adjust_pointer_closure()); + StringTable::oops_do(&oop_closure); + ref_processor()->weak_oops_do(&oop_closure); // Roots were visited so references into the young gen in roots // may have been scanned. Process them also. // Should the reference processor have a span that excludes // young gen objects? - PSScavenge::reference_processor()->weak_oops_do(adjust_pointer_closure()); + PSScavenge::reference_processor()->weak_oops_do(&oop_closure); } // Helper class to print 8 region numbers per line and then print the total at the end. @@ -3062,18 +3065,20 @@ void MoveAndUpdateClosure::copy_partial_obj() update_state(words); } -void InstanceKlass::oop_pc_update_pointers(oop obj) { - oop_oop_iterate_oop_maps(obj, PSParallelCompact::adjust_pointer_closure()); +void InstanceKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { + PSParallelCompact::AdjustPointerClosure closure(cm); + oop_oop_iterate_oop_maps(obj, &closure); } -void InstanceMirrorKlass::oop_pc_update_pointers(oop obj) { - InstanceKlass::oop_pc_update_pointers(obj); +void InstanceMirrorKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { + InstanceKlass::oop_pc_update_pointers(obj, cm); - oop_oop_iterate_statics(obj, PSParallelCompact::adjust_pointer_closure()); + PSParallelCompact::AdjustPointerClosure closure(cm); + oop_oop_iterate_statics(obj, &closure); } -void InstanceClassLoaderKlass::oop_pc_update_pointers(oop obj) { - InstanceKlass::oop_pc_update_pointers(obj); +void InstanceClassLoaderKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { + InstanceKlass::oop_pc_update_pointers(obj, cm); } #ifdef ASSERT @@ -3092,33 +3097,34 @@ template static void trace_reference_gc(const char *s, oop obj, #endif template -static void oop_pc_update_pointers_specialized(oop obj) { +static void oop_pc_update_pointers_specialized(oop obj, ParCompactionManager* cm) { T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); - PSParallelCompact::adjust_pointer(referent_addr); + PSParallelCompact::adjust_pointer(referent_addr, cm); T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); - PSParallelCompact::adjust_pointer(next_addr); + PSParallelCompact::adjust_pointer(next_addr, cm); T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); - PSParallelCompact::adjust_pointer(discovered_addr); + PSParallelCompact::adjust_pointer(discovered_addr, cm); debug_only(trace_reference_gc("InstanceRefKlass::oop_update_ptrs", obj, referent_addr, next_addr, discovered_addr);) } -void InstanceRefKlass::oop_pc_update_pointers(oop obj) { - InstanceKlass::oop_pc_update_pointers(obj); +void InstanceRefKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { + InstanceKlass::oop_pc_update_pointers(obj, cm); if (UseCompressedOops) { - oop_pc_update_pointers_specialized(obj); + oop_pc_update_pointers_specialized(obj, cm); } else { - oop_pc_update_pointers_specialized(obj); + oop_pc_update_pointers_specialized(obj, cm); } } -void ObjArrayKlass::oop_pc_update_pointers(oop obj) { +void ObjArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { assert(obj->is_objArray(), "obj must be obj array"); - oop_oop_iterate_elements(objArrayOop(obj), PSParallelCompact::adjust_pointer_closure()); + PSParallelCompact::AdjustPointerClosure closure(cm); + oop_oop_iterate_elements(objArrayOop(obj), &closure); } -void TypeArrayKlass::oop_pc_update_pointers(oop obj) { +void TypeArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { assert(obj->is_typeArray(),"must be a type array"); } @@ -3128,7 +3134,7 @@ MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) { assert(bitmap()->obj_size(addr) == words, "bad size"); _source = addr; - assert(PSParallelCompact::summary_data().calc_new_pointer(source()) == + assert(PSParallelCompact::summary_data().calc_new_pointer(source(), compaction_manager()) == destination(), "wrong destination"); if (words > words_remaining()) { diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp index cac1823ce14..ec695e04a88 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp @@ -451,10 +451,10 @@ public: HeapWord* partial_obj_end(size_t region_idx) const; // Return the location of the object after compaction. - HeapWord* calc_new_pointer(HeapWord* addr); + HeapWord* calc_new_pointer(HeapWord* addr, ParCompactionManager* cm); - HeapWord* calc_new_pointer(oop p) { - return calc_new_pointer((HeapWord*) p); + HeapWord* calc_new_pointer(oop p, ParCompactionManager* cm) { + return calc_new_pointer((HeapWord*) p, cm); } #ifdef ASSERT @@ -937,17 +937,29 @@ class PSParallelCompact : AllStatic { class AdjustPointerClosure: public ExtendedOopClosure { public: + AdjustPointerClosure(ParCompactionManager* cm) { + assert(cm != NULL, "associate ParCompactionManage should not be NULL"); + _cm = cm; + } template void do_oop_nv(T* p); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); // This closure provides its own oop verification code. debug_only(virtual bool should_verify_oops() { return false; }) + private: + ParCompactionManager* _cm; }; class AdjustKlassClosure : public KlassClosure { public: + AdjustKlassClosure(ParCompactionManager* cm) { + assert(cm != NULL, "associate ParCompactionManage should not be NULL"); + _cm = cm; + } void do_klass(Klass* klass); + private: + ParCompactionManager* _cm; }; friend class AdjustPointerClosure; @@ -966,8 +978,6 @@ class PSParallelCompact : AllStatic { static ParallelCompactData _summary_data; static IsAliveClosure _is_alive_closure; static SpaceInfo _space_info[last_space_id]; - static AdjustPointerClosure _adjust_pointer_closure; - static AdjustKlassClosure _adjust_klass_closure; // Reference processing (used in ...follow_contents) static ReferenceProcessor* _ref_processor; @@ -1063,7 +1073,7 @@ class PSParallelCompact : AllStatic { static void summary_phase(ParCompactionManager* cm, bool maximum_compaction); // Adjust addresses in roots. Does not adjust addresses in heap. - static void adjust_roots(); + static void adjust_roots(ParCompactionManager* cm); DEBUG_ONLY(static void write_block_fill_histogram();) @@ -1109,10 +1119,6 @@ class PSParallelCompact : AllStatic { static bool initialize(); // Closure accessors - static PSParallelCompact::AdjustPointerClosure* adjust_pointer_closure() { - return &_adjust_pointer_closure; - } - static KlassClosure* adjust_klass_closure() { return (KlassClosure*)&_adjust_klass_closure; } static BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&_is_alive_closure; } // Public accessors @@ -1127,7 +1133,7 @@ class PSParallelCompact : AllStatic { static inline bool mark_obj(oop obj); static inline bool is_marked(oop obj); - template static inline void adjust_pointer(T* p); + template static inline void adjust_pointer(T* p, ParCompactionManager* cm); // Compaction support. // Return true if p is in the range [beg_addr, end_addr). diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp index 2fcc947132f..dfb2ac0d53a 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * 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,13 +42,13 @@ inline bool PSParallelCompact::mark_obj(oop obj) { } template -inline void PSParallelCompact::adjust_pointer(T* p) { +inline void PSParallelCompact::adjust_pointer(T* p, ParCompactionManager* cm) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap"); - oop new_obj = (oop)summary_data().calc_new_pointer(obj); + oop new_obj = (oop)summary_data().calc_new_pointer(obj, cm); assert(new_obj != NULL, // is forwarding ptr? "should be forwarded"); // Just always do the update unconditionally? @@ -62,7 +62,7 @@ inline void PSParallelCompact::adjust_pointer(T* p) { template void PSParallelCompact::AdjustPointerClosure::do_oop_nv(T* p) { - adjust_pointer(p); + adjust_pointer(p, _cm); } inline void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp index dde37892b09..89d6301e8d2 100644 --- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ public: void oop_ps_push_contents( oop obj, PSPromotionManager* pm); // Parallel Compact void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj); + void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif // Oop fields (and metadata) iterators diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index e6b0d8e3f40..5f91fcf742d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1050,7 +1050,7 @@ public: void oop_ps_push_contents( oop obj, PSPromotionManager* pm); // Parallel Compact void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj); + void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif // Oop fields (and metadata) iterators diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp index 59db02c737e..48baee477d7 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ class InstanceMirrorKlass: public InstanceKlass { void oop_ps_push_contents( oop obj, PSPromotionManager* pm); // Parallel Compact void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj); + void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif // Oop fields (and metadata) iterators diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.hpp b/hotspot/src/share/vm/oops/instanceRefKlass.hpp index 13b7841d64c..4de86a4c7ff 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ class InstanceRefKlass: public InstanceKlass { void oop_ps_push_contents( oop obj, PSPromotionManager* pm); // Parallel Compact void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj); + void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif // Oop fields (and metadata) iterators diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 1f05ba24aaa..17b3b5b8f5f 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -578,7 +578,7 @@ protected: virtual void oop_ps_push_contents( oop obj, PSPromotionManager* pm) = 0; // Parallel Compact virtual void oop_pc_follow_contents(oop obj, ParCompactionManager* cm) = 0; - virtual void oop_pc_update_pointers(oop obj) = 0; + virtual void oop_pc_update_pointers(oop obj, ParCompactionManager* cm) = 0; #endif // Iterators specialized to particular subtypes diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index 17d2b43e4ef..bb364a89103 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,7 +116,7 @@ class ObjArrayKlass : public ArrayKlass { void oop_ps_push_contents( oop obj, PSPromotionManager* pm); // Parallel Compact void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj); + void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif // Oop fields (and metadata) iterators diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index e944e601378..d154f966568 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -330,8 +330,8 @@ class oopDesc { inline int ms_adjust_pointers(); #if INCLUDE_ALL_GCS // Parallel Compact - inline void pc_follow_contents(ParCompactionManager* pc); - inline void pc_update_contents(); + inline void pc_follow_contents(ParCompactionManager* cm); + inline void pc_update_contents(ParCompactionManager* cm); // Parallel Scavenge inline void ps_push_contents(PSPromotionManager* pm); #endif diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 8390d32501f..73c7142de60 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -650,11 +650,11 @@ void oopDesc::pc_follow_contents(ParCompactionManager* cm) { klass()->oop_pc_follow_contents(this, cm); } -void oopDesc::pc_update_contents() { +void oopDesc::pc_update_contents(ParCompactionManager* cm) { Klass* k = klass(); if (!k->is_typeArray_klass()) { // It might contain oops beyond the header, so take the virtual call. - k->oop_pc_update_pointers(this); + k->oop_pc_update_pointers(this, cm); } // Else skip it. The TypeArrayKlass in the header never needs scavenging. } diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.hpp b/hotspot/src/share/vm/oops/typeArrayKlass.hpp index e357717e476..acdf5c38a78 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,7 @@ class TypeArrayKlass : public ArrayKlass { void oop_ps_push_contents( oop obj, PSPromotionManager* pm); // Parallel Compact void oop_pc_follow_contents(oop obj, ParCompactionManager* cm); - void oop_pc_update_pointers(oop obj); + void oop_pc_update_pointers(oop obj, ParCompactionManager* cm); #endif // Oop iterators. Since there are no oops in TypeArrayKlasses, From f55f9a60a797dc49f902e6728c3665934957aedf Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 28 Jan 2016 14:00:20 +0100 Subject: [PATCH 020/139] 8147087: Race when reusing PerRegionTable bitmaps may result in dropped remembered set entries Do not make reused PRTs available to other threads before the bitmap of the PRT has been cleared. Co-authored-by: Poonam Bajaj Reviewed-by: tbenson, mgerdin --- .../src/share/vm/gc/g1/heapRegionRemSet.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 30fed52f93c..56fc9504fad 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,7 +110,9 @@ protected: public: - HeapRegion* hr() const { return _hr; } + HeapRegion* hr() const { + return (HeapRegion*) OrderAccess::load_ptr_acquire(&_hr); + } jint occupied() const { // Overkill, but if we ever need it... @@ -123,10 +125,12 @@ public: set_next(NULL); set_prev(NULL); } - _hr = hr; _collision_list_next = NULL; _occupied = 0; _bm.clear(); + // Make sure that the bitmap clearing above has been finished before publishing + // this PRT to concurrent threads. + OrderAccess::release_store_ptr(&_hr, hr); } void add_reference(OopOrNarrowOopStar from) { @@ -357,7 +361,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift); if (G1FromCardCache::contains_or_replace(tid, cur_hrm_ind, from_card)) { - assert(contains_reference(from), "We just added it!"); + assert(contains_reference(from), "We just found " PTR_FORMAT " in the FromCardCache", p2i(from)); return; } @@ -367,7 +371,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { // If the region is already coarsened, return. if (_coarse_map.at(from_hrm_ind)) { - assert(contains_reference(from), "We just added it!"); + assert(contains_reference(from), "We just found " PTR_FORMAT " in the Coarse table", p2i(from)); return; } @@ -388,7 +392,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { "Must be in range."); if (G1HRRSUseSparseTable && _sparse_table.add_card(from_hrm_ind, card_index)) { - assert(contains_reference_locked(from), "We just added it!"); + assert(contains_reference_locked(from), "We just added " PTR_FORMAT " to the Sparse table", p2i(from)); return; } @@ -438,7 +442,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { assert(prt != NULL, "Inv"); prt->add_reference(from); - assert(contains_reference(from), "We just added it!"); + assert(contains_reference(from), "We just added " PTR_FORMAT " to the PRT", p2i(from)); } PerRegionTable* From 68bb8508351103cb8e05e7f781fda33afb195b14 Mon Sep 17 00:00:00 2001 From: Alexander Harlap Date: Thu, 28 Jan 2016 16:05:41 -0500 Subject: [PATCH 021/139] 8147906: G1 use of os::processor_count() Use os::active_processor_count() instead of os::processor_count() in G1 Reviewed-by: dholmes, jmasa --- hotspot/src/share/vm/gc/g1/concurrentMark.cpp | 6 +++--- hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp index a7c70b9483e..69d6ca11eaa 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -489,11 +489,11 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / (double) GCPauseIntervalMillis; - double cpu_ratio = 1.0 / (double) os::processor_count(); + double cpu_ratio = 1.0 / (double) os::active_processor_count(); double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); double marking_task_overhead = overall_cm_overhead / marking_thread_num * - (double) os::processor_count(); + (double) os::active_processor_count(); double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index 155faa0be5a..b7dbd9e88b8 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -160,7 +160,7 @@ DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : // Determines how many mutator threads can process the buffers in parallel. uint DirtyCardQueueSet::num_par_ids() { - return (uint)os::processor_count(); + return (uint)os::active_processor_count(); } void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, From a5f97662f59cf3bcba82ec4ff2a77ed947561820 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 28 Jan 2016 15:13:15 -0800 Subject: [PATCH 022/139] 8148470: Metadata print routines should not print to tty Reviewed-by: iklam, mgerdin --- hotspot/src/share/vm/oops/metadata.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/oops/metadata.hpp b/hotspot/src/share/vm/oops/metadata.hpp index dc52c452ee3..c42997292e2 100644 --- a/hotspot/src/share/vm/oops/metadata.hpp +++ b/hotspot/src/share/vm/oops/metadata.hpp @@ -58,13 +58,13 @@ class Metadata : public MetaspaceObj { if (this == NULL) st->print("NULL"); else - print_on(tty); + print_on(st); } void print_value_on_maybe_null(outputStream* st) const { if (this == NULL) st->print("NULL"); else - print_value_on(tty); + print_value_on(st); } virtual void print_on(outputStream* st) const; // First level print From 2e5c6d4ea4747ff4e20237bf218812aa99f67921 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Fri, 29 Jan 2016 10:44:15 +0100 Subject: [PATCH 023/139] 8148467: Consistent use of : in the logging Reviewed-by: mgerdin, tbenson --- hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 0f435abe90a..df6e8ffbfac 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -2310,7 +2310,7 @@ void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) { // whether we added any apparently expensive regions or not, to // avoid generating output per region. log_debug(gc, ergo, cset)("Added expensive regions to CSet (old CSet region num not reached min)." - "old %u regions, expensive: %u regions, min %u regions, remaining time: %1.2fms", + "old: %u regions, expensive: %u regions, min: %u regions, remaining time: %1.2fms", old_cset_region_length(), expensive_region_num, min_old_cset_length, time_remaining_ms); } @@ -2319,7 +2319,7 @@ void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) { stop_incremental_cset_building(); - log_debug(gc, ergo, cset)("Finish choosing CSet. old %u regions, predicted old region time: %1.2fms, time remaining: %1.2f", + log_debug(gc, ergo, cset)("Finish choosing CSet. old: %u regions, predicted old region time: %1.2fms, time remaining: %1.2f", old_cset_region_length(), predicted_old_time_ms, time_remaining_ms); double non_young_end_time_sec = os::elapsedTime(); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index c6b7fed4fdf..0e5bb47b495 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -125,7 +125,7 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup:", true, 2); _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup:", true, 2); - _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty", true, 3); + _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty:", true, 3); _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:", true, 3); _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); } From 1875f65a5434aa89c559076031b88a3cb060acc4 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Fri, 29 Jan 2016 05:32:12 -0500 Subject: [PATCH 024/139] 6515172: Runtime.availableProcessors() ignores Linux taskset command Extract processor count from sched_getaffinity mask Reviewed-by: dcubed, stuefe, gthornbr --- hotspot/src/os/linux/vm/globals_linux.hpp | 7 +- hotspot/src/os/linux/vm/os_linux.cpp | 81 ++++++++++++-- hotspot/src/share/vm/logging/logTag.hpp | 3 +- .../test/runtime/os/AvailableProcessors.java | 102 ++++++++++++++++++ 4 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 hotspot/test/runtime/os/AvailableProcessors.java diff --git a/hotspot/src/os/linux/vm/globals_linux.hpp b/hotspot/src/os/linux/vm/globals_linux.hpp index 29e450f8dbe..05f4c181336 100644 --- a/hotspot/src/os/linux/vm/globals_linux.hpp +++ b/hotspot/src/os/linux/vm/globals_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,10 @@ "Load DLLs with executable-stack attribute in the VM Thread") \ \ product(bool, UseSHM, false, \ - "Use SYSV shared memory for large pages") + "Use SYSV shared memory for large pages") \ + \ + diagnostic(bool, UseCpuAllocPath, false, \ + "Use CPU_ALLOC code path in os::active_processor_count ") // // Defines Linux-specific default values. The flags are available on all diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 7e01a577d5b..61406a11ddf 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_linux.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_linux.inline.hpp" @@ -106,6 +107,14 @@ # include # include +#ifndef _GNU_SOURCE + #define _GNU_SOURCE + #include + #undef _GNU_SOURCE +#else + #include +#endif + // if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling // getrusage() is prepared to handle the associated failure. #ifndef RUSAGE_THREAD @@ -4762,12 +4771,72 @@ void os::make_polling_page_readable(void) { } } +// Get the current number of available processors for this process. +// This value can change at any time during a process's lifetime. +// sched_getaffinity gives an accurate answer as it accounts for cpusets. +// If it appears there may be more than 1024 processors then we do a +// dynamic check - see 6515172 for details. +// If anything goes wrong we fallback to returning the number of online +// processors - which can be greater than the number available to the process. int os::active_processor_count() { - // Linux doesn't yet have a (official) notion of processor sets, - // so just return the number of online processors. - int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); - assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check"); - return online_cpus; + cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors + cpu_set_t* cpus_p = &cpus; + int cpus_size = sizeof(cpu_set_t); + + int configured_cpus = processor_count(); // upper bound on available cpus + int cpu_count = 0; + + // To enable easy testing of the dynamic path on different platforms we + // introduce a diagnostic flag: UseCpuAllocPath + if (configured_cpus >= CPU_SETSIZE || UseCpuAllocPath) { + // kernel may use a mask bigger than cpu_set_t + log_trace(os)("active_processor_count: using dynamic path %s" + "- configured processors: %d", + UseCpuAllocPath ? "(forced) " : "", + configured_cpus); + cpus_p = CPU_ALLOC(configured_cpus); + if (cpus_p != NULL) { + cpus_size = CPU_ALLOC_SIZE(configured_cpus); + // zero it just to be safe + CPU_ZERO_S(cpus_size, cpus_p); + } + else { + // failed to allocate so fallback to online cpus + int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); + log_trace(os)("active_processor_count: " + "CPU_ALLOC failed (%s) - using " + "online processor count: %d", + strerror(errno), online_cpus); + return online_cpus; + } + } + else { + log_trace(os)("active_processor_count: using static path - configured processors: %d", + configured_cpus); + } + + // pid 0 means the current thread - which we have to assume represents the process + if (sched_getaffinity(0, cpus_size, cpus_p) == 0) { + if (cpus_p != &cpus) { + cpu_count = CPU_COUNT_S(cpus_size, cpus_p); + } + else { + cpu_count = CPU_COUNT(cpus_p); + } + log_trace(os)("active_processor_count: sched_getaffinity processor count: %d", cpu_count); + } + else { + cpu_count = ::sysconf(_SC_NPROCESSORS_ONLN); + warning("sched_getaffinity failed (%s)- using online processor count (%d) " + "which may exceed available processors", strerror(errno), cpu_count); + } + + if (cpus_p != &cpus) { + CPU_FREE(cpus_p); + } + + assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check"); + return cpu_count; } void os::set_native_thread_name(const char *name) { diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index aeedd0b2043..9f166118219 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,7 @@ LOG_TAG(marking) \ LOG_TAG(metaspace) \ LOG_TAG(monitorinflation) \ + LOG_TAG(os) \ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ diff --git a/hotspot/test/runtime/os/AvailableProcessors.java b/hotspot/test/runtime/os/AvailableProcessors.java new file mode 100644 index 00000000000..4188a11d914 --- /dev/null +++ b/hotspot/test/runtime/os/AvailableProcessors.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.File; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.OutputAnalyzer; +import java.util.ArrayList; + +/* + * @test + * @bug 6515172 + * @summary Check that availableProcessors reports the correct value when running in a cpuset on linux + * @requires os.family == "linux" + * @library /testlibrary + * @build jdk.test.lib.* + * @run driver AvailableProcessors + */ +public class AvailableProcessors { + + static final String SUCCESS_STRING = "Found expected processors: "; + + public static void main(String[] args) throws Exception { + if (args.length > 0) + checkProcessors(Integer.parseInt(args[0])); + else { + // run ourselves under different cpu configurations + // using the taskset command + String taskset; + final String taskset1 = "/bin/taskset"; + final String taskset2 = "/usr/bin/taskset"; + if (new File(taskset1).exists()) + taskset = taskset1; + else if (new File(taskset2).exists()) + taskset = taskset2; + else { + System.out.println("Skipping test: could not find taskset command"); + return; + } + + int available = Runtime.getRuntime().availableProcessors(); + + if (available == 1) { + System.out.println("Skipping test: only one processor available"); + return; + } + + // Get the java command we want to execute + // Enable logging for easier failure diagnosis + ProcessBuilder master = + ProcessTools.createJavaProcessBuilder(false, + "-Xlog:os=trace", + "AvailableProcessors"); + + int[] expected = new int[] { 1, available/2, available-1, available }; + + for (int i : expected) { + System.out.println("Testing for " + i + " processors ..."); + int max = i - 1; + ArrayList cmdline = new ArrayList<>(master.command()); + // prepend taskset command + cmdline.add(0, "0-" + max); + cmdline.add(0, "-c"); + cmdline.add(0, taskset); + // append expected processor count + cmdline.add(String.valueOf(i)); + ProcessBuilder pb = new ProcessBuilder(cmdline); + System.out.println("Final command line: " + + ProcessTools.getCommandLine(pb)); + OutputAnalyzer output = ProcessTools.executeProcess(pb); + output.shouldContain(SUCCESS_STRING); + } + } + } + + static void checkProcessors(int expected) { + int available = Runtime.getRuntime().availableProcessors(); + if (available != expected) + throw new Error("Expected " + expected + " processors, but found " + + available); + else + System.out.println(SUCCESS_STRING + available); + } +} From ed48b11dbfbf6ef595140ae96d96de6bbe9e7987 Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Fri, 29 Jan 2016 16:17:05 +0400 Subject: [PATCH 025/139] 8134963: [Newtest] New stress test for changing the coarseness level of G1 remembered set Reviewed-by: tschatzl, mchernov --- .../stress/gc/TestStressRSetCoarsening.java | 335 ++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 hotspot/test/stress/gc/TestStressRSetCoarsening.java diff --git a/hotspot/test/stress/gc/TestStressRSetCoarsening.java b/hotspot/test/stress/gc/TestStressRSetCoarsening.java new file mode 100644 index 00000000000..10ac597facc --- /dev/null +++ b/hotspot/test/stress/gc/TestStressRSetCoarsening.java @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.concurrent.TimeoutException; +import sun.hotspot.WhiteBox; + +/* + * @test TestStressRSetCoarsening.java + * @key stress + * @bug 8146984 8147087 + * @requires vm.gc=="G1" | vm.gc=="null" + * @requires os.maxMemory > 3G + * + * @summary Stress G1 Remembered Set by creating a lot of cross region links + * @modules java.base/sun.misc + * @library /testlibrary /test/lib + * @build sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc + * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 300 + * @run main/othervm/timeout=300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc + * -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 300 + * @run main/othervm/timeout=300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc + * -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 300 + * @run main/othervm/timeout=300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc + * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 300 + * @run main/othervm/timeout=1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc + * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 1800 + * @run main/othervm/timeout=1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC + * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc + * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 1800 + */ + +/** + * What the test does. + * Preparation stage: + * Fill out ~90% of the heap with objects, each object is an object array. + * If we want to allocate K objects per region, we calculate N to meet: + * sizeOf(Object[N]) ~= regionSize / K + * Stress stage: + * No more allocation, so no more GC. + * We will perform a number of iterations. On each iteration i, + * for each pair of regions Rx and Ry we will set c[i] references + * from Rx to Ry. If c[i] less than c[i-1] at the end of iteration + * concurrent mark cycle will be initiated (to recalculate remembered sets). + * As the result RSet will be growing up and down, up and down many times. + * + * The test expects: no crash and no timeouts. + * + * Test Parameters: + * args[0] - number of objects per Heap Region (1 - means humongous) + * args[1] - number of regions to refresh to provoke GC at the end of cycle. + * (0 - means no GC, i.e. no reading from RSet) + * args[2] - timeout in seconds (to stop execution to avoid jtreg timeout) + */ +public class TestStressRSetCoarsening { + + public static void main(String... args) throws InterruptedException { + if (args.length != 3) { + throw new IllegalArgumentException("Wrong number of arguments " + args.length); + } + int objectsPerRegion = Integer.parseInt(args[0]); // 1 means humongous + int regsToRefresh = Integer.parseInt(args[1]); // 0 means no regions to refresh at the end of cycle + int timeout = Integer.parseInt(args[2]); // in seconds, test should stop working eariler + new TestStressRSetCoarsening(objectsPerRegion, regsToRefresh, timeout).go(); + } + + private static final long KB = 1024; + private static final long MB = 1024 * KB; + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + public final Object[][] storage; + + /** + * Number of objects per region. This is a test parameter. + */ + public final int K; + + /** + * Length of object array: sizeOf(Object[N]) ~= regionSize / K + * N will be calculated as function of K. + */ + public final int N; + + /** + * How many regions involved into testing. + * Will be calculated as heapFractionToAllocate * freeRegionCount. + */ + public final int regionCount; + + /** + * How much heap to use. + */ + public final float heapFractionToAllocate = 0.9f; + + /** + * How many regions to be refreshed at the end of cycle. + * This is a test parameter. + */ + public final int regsToRefresh; + + /** + * Initial time. + */ + public final long start; + + /** + * Time when the test should stop working. + */ + public final long finishAt; + + /** + * Does pre-calculation and allocate necessary objects. + * + * @param objPerRegions how many objects per G1 heap region + */ + TestStressRSetCoarsening(int objPerRegions, int regsToRefresh, int timeout) { + this.K = objPerRegions; + this.regsToRefresh = regsToRefresh; + this.start = System.currentTimeMillis(); + this.finishAt = start + timeout * 900; // 10% ahead of jtreg timeout + + long regionSize = WB.g1RegionSize(); + + // How many free regions + Runtime rt = Runtime.getRuntime(); + long used = rt.totalMemory() - rt.freeMemory(); + long totalFree = rt.maxMemory() - used; + regionCount = (int) ((totalFree / regionSize) * heapFractionToAllocate); + long toAllocate = regionCount * regionSize; + System.out.println("%% Test parameters"); + System.out.println("%% Objects per region : " + K); + System.out.println("%% Heap fraction to allocate : " + (int) (heapFractionToAllocate * 100) + "%"); + System.out.println("%% Regions to refresh to provoke GC: " + regsToRefresh); + + System.out.println("%% Memory"); + System.out.println("%% used : " + used / MB + "M"); + System.out.println("%% available : " + totalFree / MB + "M"); + System.out.println("%% to allocate : " + toAllocate / MB + "M"); + System.out.println("%% (in regs) : " + regionCount); + System.out.println("%% G1 Region Size: " + regionSize / MB + "M"); + + int refSize = WB.getHeapOopSize(); + + // Calculate N: K*sizeOf(Object[N]) ~= regionSize + // sizeOf(Object[N]) ~= (N+4)*refSize + // ==> + // N = regionSize / K / refSize - 4; + N = (int) ((regionSize / K) / refSize) - 5; + + /* + * -------------- + * region0 storage[0] = new Object[N] + * ... + * storage[K-1] = new Object[N] + * --------------- + * region1 storage[K] = new Object[N] + * ... + * storage[2*K - 1] = new Object[N] + * -------------- + * ... + * -------------- + * regionX storage[X*K] = new Object[N] + * ... + * storage[(X+1)*K -1] = new Object[N] + * where X = HeapFraction * TotalRegions + * ------------- + */ + System.out.println("%% Objects"); + System.out.println("%% N (array length) : " + N); + System.out.println("%% K (objects in regions): " + K); + System.out.println("%% Reference size : " + refSize); + System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)"); + + storage = new Object[regionCount * K][]; + for (int i = 0; i < storage.length; i++) { + storage[i] = new Object[N]; + } + } + + public void go() throws InterruptedException { + // threshold for sparce -> fine + final int FINE = WB.getIntxVMFlag("G1RSetSparseRegionEntries").intValue(); + + // threshold for fine -> coarse + final int COARSE = WB.getIntxVMFlag("G1RSetRegionEntries").intValue(); + + // regToRegRefCounts - array of reference counts from region to region + // at the the end of iteration. + // The number of test iterations is array length - 1. + // If c[i] > c[i-1] then during the iteration i more references will + // be created. + // If c[i] < c[i-1] then some referenes will be cleaned. + int[] regToRegRefCounts = {0, FINE / 2, 0, FINE, (FINE + COARSE) / 2, 0, + COARSE, COARSE + 10, FINE + 1, FINE / 2, 0}; + + // For progress tracking + int[] progress = new int[regToRegRefCounts.length]; + progress[0] = 0; + for (int i = 1; i < regToRegRefCounts.length; i++) { + progress[i] = progress[i - 1] + Math.abs(regToRegRefCounts[i] - regToRegRefCounts[i - 1]); + } + try { + for (int i = 1; i < regToRegRefCounts.length; i++) { + int pre = regToRegRefCounts[i - 1]; + int cur = regToRegRefCounts[i]; + float prog = ((float) progress[i - 1] / progress[progress.length - 1]); + + System.out.println("%% step " + i + + " out of " + (regToRegRefCounts.length - 1) + + " (~" + (int) (100 * prog) + "% done)"); + System.out.println("%% " + pre + " --> " + cur); + for (int to = 0; to < regionCount; to++) { + // Select a celebrity object that we will install references to. + // The celebrity will be referred from all other regions. + // If the number of references after should be less than they + // were before, select NULL. + Object celebrity = cur > pre ? storage[to * K] : null; + for (int from = 0; from < regionCount; from++) { + if (to == from) { + continue; // no need to refer to itself + } + + int step = cur > pre ? +1 : -1; + for (int rn = pre; rn != cur; rn += step) { + storage[getY(to, from, rn)][getX(to, from, rn)] = celebrity; + if (System.currentTimeMillis() > finishAt) { + throw new TimeoutException(); + } + } + } + } + if (pre > cur) { + // Number of references went down. + // Need to provoke recalculation of RSet. + WB.g1StartConcMarkCycle(); + while (WB.g1InConcurrentMark()) { + Thread.sleep(1); + } + } + + // To force the use of rememebered set entries we need to provoke a GC. + // To induce some fragmentation, and some mixed GCs, we need + // to make a few objects unreachable. + for (int toClean = i * regsToRefresh; toClean < (i + 1) * regsToRefresh; toClean++) { + int to = toClean % regionCount; + // Need to remove all references from all regions to the region 'to' + for (int from = 0; from < regionCount; from++) { + if (to == from) { + continue; // no need to refer to itself + } + for (int rn = 0; rn <= cur; rn++) { + storage[getY(to, from, rn)][getX(to, from, rn)] = null; + } + } + // 'Refresh' storage elements for the region 'to' + // After that loop all 'old' objects in the region 'to' + // should become unreachable. + for (int k = 0; k < K; k++) { + storage[(to * K + k) % storage.length] = new Object[N]; + } + } + } + } catch (TimeoutException e) { + System.out.println("%% TIMEOUT!!!"); + } + long now = System.currentTimeMillis(); + System.out.println("%% Summary"); + System.out.println("%% Time spent : " + ((now - start) / 1000) + " seconds"); + System.out.println("%% Free memory left : " + Runtime.getRuntime().freeMemory() / KB + "K"); + System.out.println("%% Test passed"); + } + + /** + * Returns X index in the Storage of the reference #rn from the region + * 'from' to the region 'to'. + * + * @param to region # to refer to + * @param from region # to refer from + * @param rn number of reference + * + * @return X index in the range: [0 ... N-1] + */ + private int getX(int to, int from, int rn) { + return (rn * regionCount + to) % N; + } + + /** + * Returns Y index in the Storage of the reference #rn from the region + * 'from' to the region 'to'. + * + * @param to region # to refer to + * @param from region # to refer from + * @param rn number of reference + * + * @return Y index in the range: [0 ... K*regionCount -1] + */ + private int getY(int to, int from, int rn) { + return ((rn * regionCount + to) / N + from * K) % (regionCount * K); + } +} + From 7e4e18045af95533968754a43746098941aaab2b Mon Sep 17 00:00:00 2001 From: Yuji Kubota Date: Fri, 29 Jan 2016 15:26:44 +0300 Subject: [PATCH 026/139] 8148104: HSDB could not terminate when launched on CLI Create frame before initialize SA Reviewed-by: jbachorik, dsamersoff --- .../share/classes/sun/jvm/hotspot/HSDB.java | 12 ++++++++---- .../sun/jvm/hotspot/utilities/WorkerThread.java | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java index 901ac689e4c..6b3455bdd2f 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java @@ -141,16 +141,20 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener { return; } - agent = new HotSpotAgent(); - workerThread = new WorkerThread(); - attachMenuItems = new java.util.ArrayList(); - detachMenuItems = new java.util.ArrayList(); + // Create frame first, to catch any GUI creation issues + // before we initialize agent frame = new JFrame("HSDB - HotSpot Debugger"); frame.setSize(800, 600); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new CloseUI()); + agent = new HotSpotAgent(); + workerThread = new WorkerThread(); + attachMenuItems = new java.util.ArrayList(); + detachMenuItems = new java.util.ArrayList(); + + JMenuBar menuBar = new JMenuBar(); // diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/WorkerThread.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/WorkerThread.java index 3d6fb46a2e1..298b098c0ff 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/WorkerThread.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/WorkerThread.java @@ -35,7 +35,11 @@ public class WorkerThread { public WorkerThread() { mqb = new MessageQueueBackend(); mq = mqb.getFirstQueue(); - new Thread(new MainLoop()).start(); + + // Enable to terminate this worker during runnning by daemonize. + Thread mqthread = new Thread(new MainLoop()); + mqthread.setDaemon(true); + mqthread.start(); } /** Runs the given Runnable in the thread represented by this From adfab35d68101240b38f03ba46fe577628c31734 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 29 Jan 2016 16:03:21 +0300 Subject: [PATCH 027/139] 8147477: com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java is failing for the jdk9/hs snapshot control job Reviewed-by: gtriantafill, gziemski, dcubed, coleenp --- .../test/runtime/logging/ExceptionsTest.java | 22 ++++++++++++++++++- .../logging/ExceptionsTest_options_file | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/runtime/logging/ExceptionsTest_options_file diff --git a/hotspot/test/runtime/logging/ExceptionsTest.java b/hotspot/test/runtime/logging/ExceptionsTest.java index 0b9886e331b..3dfaec82d1e 100644 --- a/hotspot/test/runtime/logging/ExceptionsTest.java +++ b/hotspot/test/runtime/logging/ExceptionsTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8141211 + * @bug 8141211 8147477 * @summary exceptions=info output should have an exception message for interpreter methods * @library /testlibrary * @modules java.base/sun.misc @@ -32,10 +32,17 @@ * @run driver ExceptionsTest */ +import java.io.File; +import java.util.Map; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.ProcessTools; public class ExceptionsTest { + static void updateEnvironment(ProcessBuilder pb, String environmentVariable, String value) { + Map env = pb.environment(); + env.put(environmentVariable, value); + } + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain(""); @@ -65,6 +72,19 @@ public class ExceptionsTest { pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceExceptions", InternalClass.class.getName()); analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder(InternalClass.class.getName()); + updateEnvironment(pb, "_JAVA_OPTIONS", "-XX:+TraceExceptions"); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder(InternalClass.class.getName()); + updateEnvironment(pb, "JAVA_TOOL_OPTIONS", "-Xlog:exceptions=info -XX:-TraceExceptions"); + analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:VMOptionsFile=" + System.getProperty("test.src", ".") + + File.separator + "ExceptionsTest_options_file", + InternalClass.class.getName()); + analyzeOutputOn(pb); } public static class InternalClass { diff --git a/hotspot/test/runtime/logging/ExceptionsTest_options_file b/hotspot/test/runtime/logging/ExceptionsTest_options_file new file mode 100644 index 00000000000..b5f0532f96c --- /dev/null +++ b/hotspot/test/runtime/logging/ExceptionsTest_options_file @@ -0,0 +1 @@ +-XX:+TraceExceptions From 51a621db8dea9232f464ca150b53535857400b32 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Fri, 29 Jan 2016 16:25:10 -0800 Subject: [PATCH 028/139] 8145190: MinTLABSize can cause overflow problem with CMS GC Changed max range of MinTLABSize from max_uintx to max_uintx/2 Reviewed-by: jwilhelm, tbenson --- hotspot/src/share/vm/runtime/globals.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 0c45b3b89e6..5cfbf11f45d 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3260,7 +3260,7 @@ public: \ product(size_t, MinTLABSize, 2*K, \ "Minimum allowed TLAB size (in bytes)") \ - range(1, max_uintx) \ + range(1, max_uintx/2) \ constraint(MinTLABSizeConstraintFunc,AfterMemoryInit) \ \ product(size_t, TLABSize, 0, \ From ec7fb4ee2b138fb87b49003a82e1048567bb8bef Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Fri, 29 Jan 2016 20:57:09 -0500 Subject: [PATCH 029/139] 8146793: logStream::write re-formats string Eliminate re-format, add warning attribute, fix size check, fix va_list usage. Reviewed-by: mlarsson, rprotacio, jrose --- hotspot/src/share/vm/logging/log.hpp | 8 +++++--- hotspot/src/share/vm/utilities/ostream.cpp | 2 +- hotspot/src/share/vm/utilities/ostream.hpp | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.hpp b/hotspot/src/share/vm/logging/log.hpp index 8b65f0cd2dd..5c6b008f569 100644 --- a/hotspot/src/share/vm/logging/log.hpp +++ b/hotspot/src/share/vm/logging/log.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,15 +120,17 @@ class Log VALUE_OBJ_CLASS_SPEC { ATTRIBUTE_PRINTF(1, 0) static void vwrite(const char* fmt, va_list args) { char buf[LogBufferSize]; + va_list saved_args; // For re-format on buf overflow. + va_copy(saved_args, args); size_t prefix_len = LogPrefix::prefix(buf, sizeof(buf)); // Check that string fits in buffer; resize buffer if necessary int ret = os::log_vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, fmt, args); assert(ret >= 0, "Log message buffer issue"); - if ((size_t)ret > sizeof(buf)) { + if ((size_t)ret >= sizeof(buf)) { size_t newbuf_len = prefix_len + ret + 1; char* newbuf = NEW_C_HEAP_ARRAY(char, newbuf_len, mtLogging); prefix_len = LogPrefix::prefix(newbuf, newbuf_len); - ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, args); + ret = os::log_vsnprintf(newbuf + prefix_len, newbuf_len - prefix_len, fmt, saved_args); assert(ret >= 0, "Log message buffer issue"); puts(newbuf); FREE_C_HEAP_ARRAY(char, newbuf); diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index d37b9d08494..2a0fe9e22a6 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -1099,7 +1099,7 @@ bool networkStream::connect(const char *ip, short port) { void logStream::write(const char* s, size_t len) { if (len > 0 && s[len - 1] == '\n') { _current_line.write(s, len - 1); - _log_func(_current_line.as_string()); + _log_func("%s", _current_line.as_string()); _current_line.reset(); } else { _current_line.write(s, len); diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp index def5a44a405..9c2b6979879 100644 --- a/hotspot/src/share/vm/utilities/ostream.hpp +++ b/hotspot/src/share/vm/utilities/ostream.hpp @@ -27,6 +27,7 @@ #include "memory/allocation.hpp" #include "runtime/timer.hpp" +#include "utilities/globalDefinitions.hpp" class GCId; DEBUG_ONLY(class ResourceMark;) @@ -249,7 +250,7 @@ class fdStream : public outputStream { class logStream : public outputStream { private: stringStream _current_line; - void (*_log_func)(const char* fmt, ...); + void (*_log_func)(const char* fmt, ...) ATTRIBUTE_PRINTF(1, 2); public: void write(const char* s, size_t len); logStream(void (*log_func)(const char* fmt, ...)) : _log_func(log_func) {} From 97e169ac7783f998c977075a5606c55a3adcd65d Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Sat, 30 Jan 2016 11:02:29 -0500 Subject: [PATCH 030/139] 8145628: hotspot metadata classes shouldn't use HeapWordSize or heap related macros like align_object_size Use align_metadata_size, align_metadata_offset and is_metadata_aligned for metadata rather than align_object_size, etc. Use wordSize rather than HeapWordSize for metadata. Use align_ptr_up rather than align_pointer_up (all the related functions are ptr). Reviewed-by: hseigel, jmasa, cjplummer --- hotspot/src/cpu/sparc/vm/copy_sparc.hpp | 5 ++++- .../sun/jvm/hotspot/oops/ConstantPool.java | 4 ++-- .../jvm/hotspot/oops/ConstantPoolCache.java | 7 +++---- .../sun/jvm/hotspot/oops/InstanceKlass.java | 3 +-- .../classes/sun/jvm/hotspot/oops/Metadata.java | 7 ++++++- .../sun/jvm/hotspot/oops/MethodData.java | 4 ++-- .../src/share/vm/classfile/classFileParser.cpp | 4 ++-- hotspot/src/share/vm/classfile/stringTable.cpp | 4 ++-- hotspot/src/share/vm/classfile/symbolTable.cpp | 10 +++++----- hotspot/src/share/vm/gc/g1/g1Allocator.cpp | 8 ++++---- .../vm/gc/shared/collectedHeap.inline.hpp | 2 +- .../share/vm/interpreter/bytecodeTracer.cpp | 4 ++-- hotspot/src/share/vm/memory/metaspace.cpp | 10 +++++----- hotspot/src/share/vm/memory/padded.inline.hpp | 8 ++++---- hotspot/src/share/vm/memory/virtualspace.cpp | 4 ++-- hotspot/src/share/vm/oops/arrayKlass.cpp | 2 +- hotspot/src/share/vm/oops/arrayKlass.hpp | 4 ++-- hotspot/src/share/vm/oops/constMethod.cpp | 6 +++--- hotspot/src/share/vm/oops/constMethod.hpp | 6 ++---- hotspot/src/share/vm/oops/constantPool.hpp | 4 ++-- hotspot/src/share/vm/oops/cpCache.hpp | 10 +++++----- hotspot/src/share/vm/oops/instanceKlass.cpp | 8 ++++---- hotspot/src/share/vm/oops/instanceKlass.hpp | 14 +++++++------- hotspot/src/share/vm/oops/klass.hpp | 4 ++-- hotspot/src/share/vm/oops/klassVtable.cpp | 4 ++-- hotspot/src/share/vm/oops/klassVtable.hpp | 13 +++++-------- hotspot/src/share/vm/oops/method.cpp | 2 +- hotspot/src/share/vm/oops/method.hpp | 4 ++-- hotspot/src/share/vm/oops/methodData.cpp | 4 ++-- hotspot/src/share/vm/oops/methodData.hpp | 4 ++-- hotspot/src/share/vm/oops/objArrayKlass.hpp | 2 +- hotspot/src/share/vm/oops/symbol.cpp | 9 ++++----- hotspot/src/share/vm/oops/symbol.hpp | 6 +++--- hotspot/src/share/vm/oops/typeArrayKlass.hpp | 2 +- .../share/vm/utilities/globalDefinitions.cpp | 4 +++- .../share/vm/utilities/globalDefinitions.hpp | 18 +++++++++--------- 36 files changed, 108 insertions(+), 106 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp index 3d8fb0e5d5a..a9107d8dfdd 100644 --- a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,6 +180,9 @@ static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { typedef void (*_zero_Fn)(HeapWord* to, size_t count); +// Only used for heap objects, so align_object_offset. +// All other platforms pd_fill_to_aligned_words simply calls pd_fill_to_words, don't +// know why this one is different. static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) { assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index 5cbc25e8ef4..8a443833f8c 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -696,7 +696,7 @@ public class ConstantPool extends Metadata implements ClassConstants { } public long getSize() { - return Oop.alignObjectSize(headerSize + getLength()); + return alignSize(headerSize + getLength()); } //---------------------------------------------------------------------- diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java index b238cd30992..3ac3ced3615 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ public class ConstantPoolCache extends Metadata { public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } public long getSize() { - return Oop.alignObjectSize(baseOffset + getLength() * elementSize); + return alignSize(baseOffset + getLength() * elementSize); } public ConstantPoolCacheEntry getEntryAt(int i) { @@ -79,8 +79,7 @@ public class ConstantPoolCache extends Metadata { } public int getIntAt(int entry, int fld) { - //alignObjectSize ? - long offset = baseOffset + /*alignObjectSize*/entry * elementSize + fld * intSize; + long offset = baseOffset + entry * elementSize + fld * intSize; return (int) getAddress().getCIntegerAt(offset, intSize, true ); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 7e0aa876448..5369b11e101 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -242,8 +242,7 @@ public class InstanceKlass extends Klass { } public long getSize() { - return Oop.alignObjectSize(getHeaderSize() + getVtableLen() + - getItableLen() + getNonstaticOopMapSize()); + return alignSize(getHeaderSize() + getVtableLen() + getItableLen() + getNonstaticOopMapSize()); } public static long getHeaderSize() { return headerSize; } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java index 4fc2ed8c6a8..244312b97c7 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Metadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,11 @@ abstract public class Metadata extends VMObject { super(addr); } + public static long alignSize(long size) { + // natural word size. + return VM.getVM().alignUp(size, VM.getVM().getBytesPerWord()); + } + private static VirtualBaseConstructor metadataConstructor; private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java index f07b8268873..1549538a10e 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,7 +252,7 @@ public class MethodData extends Metadata implements MethodDataInterface parametersTypeData() { diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 0891794a931..b3a853deb3b 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2705,7 +2705,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, ConstMethod::NORMAL, CHECK_NULL); - ClassLoadingService::add_class_method_size(m->size()*HeapWordSize); + ClassLoadingService::add_class_method_size(m->size()*wordSize); // Fill in information from fixed part (access_flags already set) m->set_constants(_cp); diff --git a/hotspot/src/share/vm/classfile/stringTable.cpp b/hotspot/src/share/vm/classfile/stringTable.cpp index 391e21eedab..ee303426f3c 100644 --- a/hotspot/src/share/vm/classfile/stringTable.cpp +++ b/hotspot/src/share/vm/classfile/stringTable.cpp @@ -737,7 +737,7 @@ bool StringTable::copy_compact_table(char** top, char *end, GrowableArray::_string_table, (char*)p); - const char* aligned_end = (const char*)align_pointer_up(end, sizeof(void*)); + const char* aligned_end = (const char*)align_ptr_up(end, sizeof(void*)); if (_ignore_shared_strings) { _shared_table.reset(); diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp index 93ed78520cb..7574e85c8f2 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.cpp +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp @@ -544,7 +544,7 @@ bool SymbolTable::copy_compact_table(char** top, char*end) { ch_table.dump(top, end); - *top = (char*)align_pointer_up(*top, sizeof(void*)); + *top = (char*)align_ptr_up(*top, sizeof(void*)); #endif return true; } @@ -552,7 +552,7 @@ bool SymbolTable::copy_compact_table(char** top, char*end) { const char* SymbolTable::init_shared_table(const char* buffer) { const char* end = _shared_table.init( CompactHashtable::_symbol_table, buffer); - return (const char*)align_pointer_up(end, sizeof(void*)); + return (const char*)align_ptr_up(end, sizeof(void*)); } //--------------------------------------------------------------------------- @@ -600,7 +600,7 @@ void SymbolTable::print_histogram() { tty->print_cr("Symbol Table Histogram:"); tty->print_cr(" Total number of symbols %7d", total_count); tty->print_cr(" Total size in memory %7dK", - (total_size*HeapWordSize)/1024); + (total_size*wordSize)/1024); tty->print_cr(" Total counted %7d", _symbols_counted); tty->print_cr(" Total removed %7d", _symbols_removed); if (_symbols_counted > 0) { @@ -617,11 +617,11 @@ void SymbolTable::print_histogram() { tty->print_cr(" %6s %10s %10s", "Length", "#Symbols", "Size"); for (i = 0; i < results_length; i++) { if (counts[i] > 0) { - tty->print_cr(" %6d %10d %10dK", i, counts[i], (sizes[i]*HeapWordSize)/1024); + tty->print_cr(" %6d %10d %10dK", i, counts[i], (sizes[i]*wordSize)/1024); } } tty->print_cr(" >=%6d %10d %10dK\n", results_length, - out_of_range_count, (out_of_range_size*HeapWordSize)/1024); + out_of_range_count, (out_of_range_size*wordSize)/1024); } void SymbolTable::print() { diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp index d0a92be5ff7..ad5aa0c556c 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -438,7 +438,7 @@ void G1ArchiveAllocator::complete_archive(GrowableArray* ranges, // If an end alignment was requested, insert filler objects. if (end_alignment_in_bytes != 0) { HeapWord* currtop = _allocation_region->top(); - HeapWord* newtop = (HeapWord*)align_pointer_up(currtop, end_alignment_in_bytes); + HeapWord* newtop = (HeapWord*)align_ptr_up(currtop, end_alignment_in_bytes); size_t fill_size = pointer_delta(newtop, currtop); if (fill_size != 0) { if (fill_size < CollectedHeap::min_fill_size()) { @@ -447,8 +447,8 @@ void G1ArchiveAllocator::complete_archive(GrowableArray* ranges, // region boundary because the max supported alignment is smaller than the min // region size, and because the allocation code never leaves space smaller than // the min_fill_size at the top of the current allocation region. - newtop = (HeapWord*)align_pointer_up(currtop + CollectedHeap::min_fill_size(), - end_alignment_in_bytes); + newtop = (HeapWord*)align_ptr_up(currtop + CollectedHeap::min_fill_size(), + end_alignment_in_bytes); fill_size = pointer_delta(newtop, currtop); } HeapWord* fill = archive_mem_allocate(fill_size); diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp index 449f252d1d4..71b3c360044 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.inline.hpp @@ -249,7 +249,7 @@ inline HeapWord* CollectedHeap::align_allocation_or_fail(HeapWord* addr, assert(is_size_aligned(alignment_in_bytes, HeapWordSize), "Alignment size %u is incorrect.", alignment_in_bytes); - HeapWord* new_addr = (HeapWord*) align_pointer_up(addr, alignment_in_bytes); + HeapWord* new_addr = (HeapWord*) align_ptr_up(addr, alignment_in_bytes); size_t padding = pointer_delta(new_addr, addr); if (padding == 0) { diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp index a1ae0eee4a6..4cd70c85484 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -264,7 +264,7 @@ bool BytecodePrinter::check_cp_cache_index(int i, int& cp_index, outputStream* s return true; } //climit = cache->length(); // %%% private! - size_t size = cache->size() * HeapWordSize; + size_t size = cache->size() * wordSize; size -= sizeof(ConstantPoolCache); size /= sizeof(ConstantPoolCacheEntry); climit = (int) size; diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index f430b446c04..39b8c2c5917 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3474,7 +3474,7 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, } // Zero initialize. - Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); + Copy::fill_to_words((HeapWord*)result, word_size, 0); return result; } @@ -3513,7 +3513,7 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, } // Zero initialize. - Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); + Copy::fill_to_words((HeapWord*)result, word_size, 0); return result; } @@ -3583,7 +3583,7 @@ const char* Metaspace::metadata_type_name(Metaspace::MetadataType mdtype) { void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) { assert(DumpSharedSpaces, "sanity"); - int byte_size = (int)word_size * HeapWordSize; + int byte_size = (int)word_size * wordSize; AllocRecord *rec = new AllocRecord((address)ptr, type, byte_size); if (_alloc_record_head == NULL) { @@ -3623,7 +3623,7 @@ void Metaspace::record_deallocation(void* ptr, size_t word_size) { for (AllocRecord *rec = _alloc_record_head; rec; rec = rec->_next) { if (rec->_ptr == ptr) { - assert(rec->_byte_size == (int)word_size * HeapWordSize, "sanity"); + assert(rec->_byte_size == (int)word_size * wordSize, "sanity"); rec->_type = MetaspaceObj::DeallocatedType; return; } diff --git a/hotspot/src/share/vm/memory/padded.inline.hpp b/hotspot/src/share/vm/memory/padded.inline.hpp index 53404f3909b..15dfb38fd24 100644 --- a/hotspot/src/share/vm/memory/padded.inline.hpp +++ b/hotspot/src/share/vm/memory/padded.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ PaddedEnd* PaddedArray::create_unfreeable(uint length) { void* chunk = AllocateHeap(length * sizeof(PaddedEnd) + alignment, flags); // Make the initial alignment. - PaddedEnd* aligned_padded_array = (PaddedEnd*)align_pointer_up(chunk, alignment); + PaddedEnd* aligned_padded_array = (PaddedEnd*)align_ptr_up(chunk, alignment); // Call the default constructor for each element. for (uint i = 0; i < length; i++) { @@ -65,7 +65,7 @@ T** Padded2DArray::create_unfreeable(uint rows, uint column // Clear the allocated memory. memset(chunk, 0, total_size); // Align the chunk of memory. - T** result = (T**)align_pointer_up(chunk, alignment); + T** result = (T**)align_ptr_up(chunk, alignment); void* data_start = (void*)((uintptr_t)result + table_size); // Fill in the row table. @@ -87,7 +87,7 @@ T* PaddedPrimitiveArray::create_unfreeable(size_t length) { memset(chunk, 0, length * sizeof(T) + alignment); - return (T*)align_pointer_up(chunk, alignment); + return (T*)align_ptr_up(chunk, alignment); } #endif // SHARE_VM_MEMORY_PADDED_INLINE_HPP diff --git a/hotspot/src/share/vm/memory/virtualspace.cpp b/hotspot/src/share/vm/memory/virtualspace.cpp index 433904eed00..76f45090ec2 100644 --- a/hotspot/src/share/vm/memory/virtualspace.cpp +++ b/hotspot/src/share/vm/memory/virtualspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -502,7 +502,7 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali // Calc address range within we try to attach (range of possible start addresses). char* const highest_start = (char *)align_ptr_down((char *)UnscaledOopHeapMax - size, attach_point_alignment); - char* const lowest_start = (char *)align_ptr_up ( aligned_heap_base_min_address , attach_point_alignment); + char* const lowest_start = (char *)align_ptr_up(aligned_heap_base_min_address, attach_point_alignment); try_reserve_range(highest_start, lowest_start, attach_point_alignment, aligned_heap_base_min_address, (char *)UnscaledOopHeapMax, size, alignment, large); } diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 573bcab6805..f3e02874d7d 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -43,7 +43,7 @@ int ArrayKlass::static_size(int header_size) { header_size = InstanceKlass::header_size(); int vtable_len = Universe::base_vtable_size(); int size = header_size + vtable_len; - return align_object_size(size); + return align_metadata_size(size); } diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index ef3e21d9af4..01faa793334 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,7 +99,7 @@ class ArrayKlass: public Klass { bool compute_is_subtype_of(Klass* k); // Sizing - static int header_size() { return sizeof(ArrayKlass)/HeapWordSize; } + static int header_size() { return sizeof(ArrayKlass)/wordSize; } static int static_size(int header_size); #if INCLUDE_SERVICES diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index ae3b1ae1076..3a5d5a7fb73 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,7 +144,7 @@ int ConstMethod::size(int code_size, int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned"); - return align_object_size(header_size() + extra_words); + return align_metadata_size(header_size() + extra_words); } Method* ConstMethod::method() const { @@ -492,6 +492,6 @@ void ConstMethod::verify_on(outputStream* st) { uncompressed_table_start = (u2*) m_end; } int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end; - int max_gap = align_object_size(1)*BytesPerWord; + int max_gap = align_metadata_size(1)*BytesPerWord; guarantee(gap >= 0 && gap < max_gap, "invalid method layout"); } diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 5bd135ebf17..7d959fb516b 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -328,9 +328,7 @@ public: } // Sizing - static int header_size() { - return sizeof(ConstMethod)/HeapWordSize; - } + static int header_size() { return sizeof(ConstMethod)/wordSize; } // Size needed static int size(int code_size, InlineTableSizes* sizes); diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index c50c8c57045..9ed795cb303 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -723,8 +723,8 @@ class ConstantPool : public Metadata { } // Sizing (in words) - static int header_size() { return sizeof(ConstantPool)/HeapWordSize; } - static int size(int length) { return align_object_size(header_size() + length); } + static int header_size() { return sizeof(ConstantPool)/wordSize; } + static int size(int length) { return align_metadata_size(header_size() + length); } int size() const { return size(length()); } #if INCLUDE_SERVICES void collect_statistics(KlassSizeStats *sz) const; diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index cf6731da613..33828d52f6a 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -364,7 +364,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } // Code generation support - static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); } + static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / wordSize); } static ByteSize size_in_bytes() { return in_ByteSize(sizeof(ConstantPoolCacheEntry)); } static ByteSize indices_offset() { return byte_offset_of(ConstantPoolCacheEntry, _indices); } static ByteSize f1_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f1); } @@ -439,14 +439,14 @@ class ConstantPoolCache: public MetaspaceObj { private: void set_length(int length) { _length = length; } - static int header_size() { return sizeof(ConstantPoolCache) / HeapWordSize; } - static int size(int length) { return align_object_size(header_size() + length * in_words(ConstantPoolCacheEntry::size())); } + static int header_size() { return sizeof(ConstantPoolCache) / wordSize; } + static int size(int length) { return align_metadata_size(header_size() + length * in_words(ConstantPoolCacheEntry::size())); } public: int size() const { return size(length()); } private: // Helpers - ConstantPool** constant_pool_addr() { return &_constant_pool; } + ConstantPool** constant_pool_addr() { return &_constant_pool; } ConstantPoolCacheEntry* base() const { return (ConstantPoolCacheEntry*)((address)this + in_bytes(base_offset())); } friend class constantPoolCacheKlass; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index f96838b4b5b..84a4c6edacf 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2909,10 +2909,10 @@ const char* InstanceKlass::internal_name() const { void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { Klass::collect_statistics(sz); - sz->_inst_size = HeapWordSize * size_helper(); - sz->_vtab_bytes = HeapWordSize * vtable_length(); - sz->_itab_bytes = HeapWordSize * itable_length(); - sz->_nonstatic_oopmap_bytes = HeapWordSize * nonstatic_oop_map_size(); + sz->_inst_size = wordSize * size_helper(); + sz->_vtab_bytes = wordSize * vtable_length(); + sz->_itab_bytes = wordSize * itable_length(); + sz->_nonstatic_oopmap_bytes = wordSize * nonstatic_oop_map_size(); int n = 0; n += (sz->_methods_array_bytes = sz->count_array(methods())); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 5f91fcf742d..d807aa2ce55 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -94,10 +94,10 @@ class OopMapBlock VALUE_OBJ_CLASS_SPEC { uint count() const { return _count; } void set_count(uint count) { _count = count; } - // sizeof(OopMapBlock) in HeapWords. + // sizeof(OopMapBlock) in words. static const int size_in_words() { - return align_size_up(int(sizeof(OopMapBlock)), HeapWordSize) >> - LogHeapWordSize; + return align_size_up(int(sizeof(OopMapBlock)), wordSize) >> + LogBytesPerWord; } private: @@ -927,17 +927,17 @@ public: } // Sizing (in words) - static int header_size() { return sizeof(InstanceKlass)/HeapWordSize; } + static int header_size() { return sizeof(InstanceKlass)/wordSize; } static int size(int vtable_length, int itable_length, int nonstatic_oop_map_size, bool is_interface, bool is_anonymous) { - return align_object_size(header_size() + + return align_metadata_size(header_size() + vtable_length + itable_length + nonstatic_oop_map_size + - (is_interface ? (int)sizeof(Klass*)/HeapWordSize : 0) + - (is_anonymous ? (int)sizeof(Klass*)/HeapWordSize : 0)); + (is_interface ? (int)sizeof(Klass*)/wordSize : 0) + + (is_anonymous ? (int)sizeof(Klass*)/wordSize : 0)); } int size() const { return size(vtable_length(), itable_length(), diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 17b3b5b8f5f..21616a01da1 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -352,13 +352,13 @@ protected: | (log2_esize << _lh_log2_element_size_shift); } static jint instance_layout_helper(jint size, bool slow_path_flag) { - return (size << LogHeapWordSize) + return (size << LogBytesPerWord) | (slow_path_flag ? _lh_instance_slow_path_bit : 0); } static int layout_helper_to_size_helper(jint lh) { assert(lh > (jint)_lh_neutral_value, "must be instance"); // Note that the following expression discards _lh_instance_slow_path_bit. - return lh >> LogHeapWordSize; + return lh >> LogBytesPerWord; } // Out-of-line version computes everything based on the etype: static jint array_layout_helper(BasicType etype); diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 164532185e9..090e5e8b9c5 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1331,7 +1331,7 @@ int klassItable::compute_itable_size(Array* transitive_interfaces) { int itable_size = calc_itable_size(cic.nof_interfaces() + 1, cic.nof_methods()); // Statistics - update_stats(itable_size * HeapWordSize); + update_stats(itable_size * wordSize); return itable_size; } diff --git a/hotspot/src/share/vm/oops/klassVtable.hpp b/hotspot/src/share/vm/oops/klassVtable.hpp index 4127a1961eb..0b4e23fa22e 100644 --- a/hotspot/src/share/vm/oops/klassVtable.hpp +++ b/hotspot/src/share/vm/oops/klassVtable.hpp @@ -170,12 +170,9 @@ class vtableEntry VALUE_OBJ_CLASS_SPEC { public: // size in words - static int size() { - return sizeof(vtableEntry) / sizeof(HeapWord); - } - static int size_in_bytes() { - return sizeof(vtableEntry); - } + static int size() { return sizeof(vtableEntry) / wordSize; } + static int size_in_bytes() { return sizeof(vtableEntry); } + static int method_offset_in_bytes() { return offset_of(vtableEntry, _method); } Method* method() const { return _method; } @@ -226,7 +223,7 @@ class itableOffsetEntry VALUE_OBJ_CLASS_SPEC { void initialize(Klass* interf, int offset) { _interface = interf; _offset = offset; } // Static size and offset accessors - static int size() { return sizeof(itableOffsetEntry) / HeapWordSize; } // size in words + static int size() { return sizeof(itableOffsetEntry) / wordSize; } // size in words static int interface_offset_in_bytes() { return offset_of(itableOffsetEntry, _interface); } static int offset_offset_in_bytes() { return offset_of(itableOffsetEntry, _offset); } @@ -246,7 +243,7 @@ class itableMethodEntry VALUE_OBJ_CLASS_SPEC { void initialize(Method* method); // Static size and offset accessors - static int size() { return sizeof(itableMethodEntry) / HeapWordSize; } // size in words + static int size() { return sizeof(itableMethodEntry) / wordSize; } // size in words static int method_offset_in_bytes() { return offset_of(itableMethodEntry, _method); } friend class klassItable; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index a6539c67ba1..46a0c1e584e 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -295,7 +295,7 @@ int Method::size(bool is_native) { // If native, then include pointers for native_function and signature_handler int extra_bytes = (is_native) ? 2*sizeof(address*) : 0; int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; - return align_object_size(header_size() + extra_words); + return align_metadata_size(header_size() + extra_words); } diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 8bc3b7073fc..8fc7b133a16 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -622,7 +622,7 @@ class Method : public Metadata { bool has_compiled_code() const { return code() != NULL; } // sizing - static int header_size() { return sizeof(Method)/HeapWordSize; } + static int header_size() { return sizeof(Method)/wordSize; } static int size(bool is_native); int size() const { return method_size(); } #if INCLUDE_SERVICES diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index 5f278176275..319787a189a 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -934,7 +934,7 @@ int MethodData::compute_allocation_size_in_bytes(const methodHandle& method) { int MethodData::compute_allocation_size_in_words(const methodHandle& method) { int byte_size = compute_allocation_size_in_bytes(method); int word_size = align_size_up(byte_size, BytesPerWord) / BytesPerWord; - return align_object_size(word_size); + return align_metadata_size(word_size); } // Initialize an individual data segment. Returns the size of diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index c8d3d8fc247..59669602a38 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2334,7 +2334,7 @@ public: // My size int size_in_bytes() const { return _size; } - int size() const { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } + int size() const { return align_metadata_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } #if INCLUDE_SERVICES void collect_statistics(KlassSizeStats *sz) const; #endif diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index bb364a89103..eabbec56c96 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -101,7 +101,7 @@ class ObjArrayKlass : public ArrayKlass { } // Sizing - static int header_size() { return sizeof(ObjArrayKlass)/HeapWordSize; } + static int header_size() { return sizeof(ObjArrayKlass)/wordSize; } int size() const { return ArrayKlass::static_size(header_size()); } // Initialization (virtual from Klass) diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index bbac298cbd3..be5901f3f6b 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * 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,20 +42,19 @@ Symbol::Symbol(const u1* name, int length, int refcount) { } void* Symbol::operator new(size_t sz, int len, TRAPS) throw() { - int alloc_size = size(len)*HeapWordSize; + int alloc_size = size(len)*wordSize; address res = (address) AllocateHeap(alloc_size, mtSymbol); return res; } void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) throw() { - int alloc_size = size(len)*HeapWordSize; - address res = (address)arena->Amalloc(alloc_size); + int alloc_size = size(len)*wordSize; + address res = (address)arena->Amalloc_4(alloc_size); return res; } void* Symbol::operator new(size_t sz, int len, ClassLoaderData* loader_data, TRAPS) throw() { address res; - int alloc_size = size(len)*HeapWordSize; res = (address) Metaspace::allocate(loader_data, size(len), true, MetaspaceObj::SymbolType, CHECK_NULL); return res; diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index 074ee879e70..f4241d3ad8d 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,8 +125,8 @@ class Symbol : public MetaspaceObj { }; static int size(int length) { - size_t sz = heap_word_size(sizeof(Symbol) + (length > 2 ? length - 2 : 0)); - return align_object_size(sz); + // minimum number of natural words needed to hold these bits (no non-heap version) + return (int)heap_word_size(sizeof(Symbol) + (length > 2 ? length - 2 : 0)); } void byte_at_put(int index, int value) { diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.hpp b/hotspot/src/share/vm/oops/typeArrayKlass.hpp index acdf5c38a78..7f07e4fb482 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp @@ -133,7 +133,7 @@ class TypeArrayKlass : public ArrayKlass { static const char* external_name(BasicType type); // Sizing - static int header_size() { return sizeof(TypeArrayKlass)/HeapWordSize; } + static int header_size() { return sizeof(TypeArrayKlass)/wordSize; } int size() const { return ArrayKlass::static_size(header_size()); } // Initialization (virtual from Klass) diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 1491be7091e..24dedf470f2 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,6 +85,8 @@ void basic_types_init() { assert( 1 == sizeof( u1), "wrong size for basic type"); assert( 2 == sizeof( u2), "wrong size for basic type"); assert( 4 == sizeof( u4), "wrong size for basic type"); + assert(wordSize == BytesPerWord, "should be the same since they're used interchangeably"); + assert(wordSize == HeapWordSize, "should be the same since they're also used interchangeably"); int num_type_chars = 0; for (int i = 0; i < 99; i++) { diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index d5c2f20cfad..6cdb8c8ab57 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -157,7 +157,6 @@ class HeapWord { // Analogous opaque struct for metadata allocated from // metaspaces. class MetaWord { - friend class VMStructs; private: char* i; }; @@ -486,7 +485,7 @@ inline intptr_t align_size_down(intptr_t size, intptr_t alignment) { #define is_size_aligned_(size, alignment) ((size) == (align_size_up_(size, alignment))) -inline void* align_ptr_up(void* ptr, size_t alignment) { +inline void* align_ptr_up(const void* ptr, size_t alignment) { return (void*)align_size_up((intptr_t)ptr, (intptr_t)alignment); } @@ -494,10 +493,15 @@ inline void* align_ptr_down(void* ptr, size_t alignment) { return (void*)align_size_down((intptr_t)ptr, (intptr_t)alignment); } -// Align objects by rounding up their size, in HeapWord units. +// Align metaspace objects by rounding up to natural word boundary -#define align_object_size_(size) align_size_up_(size, MinObjAlignment) +inline intptr_t align_metadata_size(intptr_t size) { + return align_size_up(size, 1); +} +// Align objects in the Java Heap by rounding up their size, in HeapWord units. +// Since the size is given in words this is somewhat of a nop, but +// distinguishes it from align_object_size. inline intptr_t align_object_size(intptr_t size) { return align_size_up(size, MinObjAlignment); } @@ -512,10 +516,6 @@ inline intptr_t align_object_offset(intptr_t offset) { return align_size_up(offset, HeapWordsPerLong); } -inline void* align_pointer_up(const void* addr, size_t size) { - return (void*) align_size_up_((uintptr_t)addr, size); -} - // Align down with a lower bound. If the aligning results in 0, return 'alignment'. inline size_t align_size_down_bounded(size_t size, size_t alignment) { From 211dc93a851997eb5f95e732a0dadae0fbdbcc37 Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Tue, 1 Dec 2015 10:35:49 +0100 Subject: [PATCH 031/139] 8148047: Move the vtable length field to Klass Reviewed-by: cjplummer, twisti, coleenp, kbarrett --- .../src/cpu/aarch64/vm/macroAssembler_aarch64.cpp | 6 +++--- hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp | 2 +- hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 6 +++--- hotspot/src/cpu/ppc/vm/ppc.ad | 2 +- hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp | 2 +- hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp | 8 ++++---- hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp | 6 +++--- hotspot/src/cpu/sparc/vm/sparc.ad | 4 ++-- hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp | 4 ++-- hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp | 2 +- hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 6 +++--- hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp | 2 +- hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp | 2 +- .../classes/sun/jvm/hotspot/oops/ArrayKlass.java | 6 +----- .../sun/jvm/hotspot/oops/InstanceKlass.java | 4 ---- .../share/classes/sun/jvm/hotspot/oops/Klass.java | 7 ++++++- .../ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 2 +- .../ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 6 +++--- .../src/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 4 ++-- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 2 +- hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp | 8 ++++---- hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp | 6 +++--- hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp | 6 +++--- hotspot/src/share/vm/oops/arrayKlass.cpp | 8 ++++---- hotspot/src/share/vm/oops/arrayKlass.hpp | 4 ---- hotspot/src/share/vm/oops/instanceKlass.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.hpp | 10 +--------- hotspot/src/share/vm/oops/klass.cpp | 6 +++++- hotspot/src/share/vm/oops/klass.hpp | 14 ++++++++++++-- hotspot/src/share/vm/opto/library_call.cpp | 2 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 3 +-- hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp | 6 +++--- 32 files changed, 78 insertions(+), 80 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 9cf1dc31ff8..5ac81bec145 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -898,13 +898,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, "caller must use same register for non-constant itable index as for method"); // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); + int vtable_base = in_bytes(Klass::vtable_start_offset()); int itentry_off = itableMethodEntry::method_offset_in_bytes(); int scan_step = itableOffsetEntry::size() * wordSize; int vte_size = vtableEntry::size_in_bytes(); assert(vte_size == wordSize, "else adjust times_vte_scale"); - ldrw(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset())); + ldrw(scan_temp, Address(recv_klass, Klass::vtable_length_offset())); // %%% Could store the aligned, prescaled offset in the klassoop. // lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); @@ -958,7 +958,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, void MacroAssembler::lookup_virtual_method(Register recv_klass, RegisterOrConstant vtable_index, Register method_result) { - const int base = in_bytes(InstanceKlass::vtable_start_offset()); + const int base = in_bytes(Klass::vtable_start_offset()); assert(vtableEntry::size() * wordSize == 8, "adjust the scaling in the code below"); int vtable_offset_in_bytes = base + vtableEntry::method_offset_in_bytes(); diff --git a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp index 56d4254efc2..223f1810a6f 100644 --- a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp @@ -73,7 +73,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { if (DebugVtables) { Label L; // check offset vs vtable length - __ ldrw(rscratch1, Address(r19, InstanceKlass::vtable_length_offset())); + __ ldrw(rscratch1, Address(r19, Klass::vtable_length_offset())); __ cmpw(rscratch1, vtable_index * vtableEntry::size()); __ br(Assembler::GT, L); __ enter(); diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index fc6556481c9..452d5db41b2 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1583,13 +1583,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, "caller must use same register for non-constant itable index as for method"); // Compute start of first itableOffsetEntry (which is at the end of the vtable). - int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); + int vtable_base = in_bytes(Klass::vtable_start_offset()); int itentry_off = itableMethodEntry::method_offset_in_bytes(); int logMEsize = exact_log2(itableMethodEntry::size() * wordSize); int scan_step = itableOffsetEntry::size() * wordSize; int log_vte_size= exact_log2(vtableEntry::size_in_bytes()); - lwz(scan_temp, in_bytes(InstanceKlass::vtable_length_offset()), recv_klass); + lwz(scan_temp, in_bytes(Klass::vtable_length_offset()), recv_klass); // %%% We should store the aligned, prescaled offset in the klassoop. // Then the next several instructions would fold away. @@ -1657,7 +1657,7 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass, assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); - const int base = in_bytes(InstanceKlass::vtable_start_offset()); + const int base = in_bytes(Klass::vtable_start_offset()); assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); if (vtable_index.is_register()) { diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 4516efb4ae3..7636e367d85 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -3562,7 +3562,7 @@ encode %{ __ load_klass(R11_scratch1, R3); - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + _vtable_index * vtableEntry::size_in_bytes(); + int entry_offset = in_bytes(Klass::vtable_start_offset()) + _vtable_index * vtableEntry::size_in_bytes(); int v_off = entry_offset + vtableEntry::method_offset_in_bytes(); __ li(R19_method, v_off); __ ldx(R19_method/*method oop*/, R19_method/*method offset*/, R11_scratch1/*class*/); diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index f963ffd70bc..b2cad669399 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -3282,7 +3282,7 @@ void TemplateTable::generate_vtable_call(Register Rrecv_klass, Register Rindex, const Register Rtarget_method = Rindex; // Get target method & entry point. - const int base = in_bytes(InstanceKlass::vtable_start_offset()); + const int base = in_bytes(Klass::vtable_start_offset()); // Calc vtable addr scale the vtable index by 8. __ sldi(Rindex, Rindex, exact_log2(vtableEntry::size_in_bytes())); // Load target. diff --git a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp index 77c97b129eb..3dc20a15ebe 100644 --- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp @@ -80,14 +80,14 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { __ load_klass(rcvr_klass, R3); // Set method (in case of interpreted method), and destination address. - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); #ifndef PRODUCT if (DebugVtables) { Label L; // Check offset vs vtable length. const Register vtable_len = R12_scratch2; - __ lwz(vtable_len, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); + __ lwz(vtable_len, in_bytes(Klass::vtable_length_offset()), rcvr_klass); __ cmpwi(CCR0, vtable_len, vtable_index*vtableEntry::size()); __ bge(CCR0, L); __ li(R12_scratch2, vtable_index); @@ -163,13 +163,13 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { __ load_klass(rcvr_klass, R3_ARG1); BLOCK_COMMENT("Load start of itable entries into itable_entry."); - __ lwz(vtable_len, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); + __ lwz(vtable_len, in_bytes(Klass::vtable_length_offset()), rcvr_klass); __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); __ add(itable_entry_addr, vtable_len, rcvr_klass); // Loop over all itable entries until desired interfaceOop(Rinterface) found. BLOCK_COMMENT("Increment itable_entry_addr in loop."); - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); __ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes()); const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index 130a7c9b966..ae572661df9 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -2188,11 +2188,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); + int vtable_base = in_bytes(Klass::vtable_start_offset()); int scan_step = itableOffsetEntry::size() * wordSize; int vte_size = vtableEntry::size_in_bytes(); - lduw(recv_klass, in_bytes(InstanceKlass::vtable_length_offset()), scan_temp); + lduw(recv_klass, in_bytes(Klass::vtable_length_offset()), scan_temp); // %%% We should store the aligned, prescaled offset in the klassoop. // Then the next several instructions would fold away. @@ -2268,7 +2268,7 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass, Register method_result) { assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); Register sethi_temp = method_result; - const int base = in_bytes(InstanceKlass::vtable_start_offset()) + + const int base = in_bytes(Klass::vtable_start_offset()) + // method pointer offset within the vtable entry: vtableEntry::method_offset_in_bytes(); RegisterOrConstant vtable_offset = vtable_index; diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 1678962fd74..6bbef4e5708 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -601,7 +601,7 @@ int MachCallDynamicJavaNode::ret_addr_offset() { NativeCall::instruction_size); // sethi; setlo; call; delay slot } else { assert(!UseInlineCaches, "expect vtable calls only if not using ICs"); - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); int v_off = entry_offset + vtableEntry::method_offset_in_bytes(); int klass_load_size; if (UseCompressedClassPointers) { @@ -2658,7 +2658,7 @@ encode %{ } else { klass_load_size = 1*BytesPerInstWord; } - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes(); int v_off = entry_offset + vtableEntry::method_offset_in_bytes(); if (Assembler::is_simm13(v_off)) { __ ld_ptr(G3, v_off, G5_method); diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 526347883b5..1315f7c8d60 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -3153,11 +3153,11 @@ void TemplateTable::invokeinterface(int byte_no) { // // compute start of first itableOffsetEntry (which is at end of vtable) - const int base = in_bytes(InstanceKlass::vtable_start_offset()); + const int base = in_bytes(Klass::vtable_start_offset()); Label search; Register Rtemp = O1_flags; - __ ld(O2_Klass, in_bytes(InstanceKlass::vtable_length_offset()), Rtemp); + __ ld(O2_Klass, in_bytes(Klass::vtable_length_offset()), Rtemp); __ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4; if (Assembler::is_simm13(base)) { __ add(Rtemp, base, Rtemp); diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index 5144d1fb971..4e717eebe9b 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -78,7 +78,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { if (DebugVtables) { Label L; // check offset vs vtable length - __ ld(G3_scratch, in_bytes(InstanceKlass::vtable_length_offset()), G5); + __ ld(G3_scratch, in_bytes(Klass::vtable_length_offset()), G5); __ cmp_and_br_short(G5, vtable_index*vtableEntry::size(), Assembler::greaterUnsigned, Assembler::pt, L); __ set(vtable_index, O2); __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), O0, O2); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index 2b19504ce28..288863524b9 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -5807,14 +5807,14 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, "caller must use same register for non-constant itable index as for method"); // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = in_bytes(InstanceKlass::vtable_start_offset()); + int vtable_base = in_bytes(Klass::vtable_start_offset()); int itentry_off = itableMethodEntry::method_offset_in_bytes(); int scan_step = itableOffsetEntry::size() * wordSize; int vte_size = vtableEntry::size_in_bytes(); Address::ScaleFactor times_vte_scale = Address::times_ptr; assert(vte_size == wordSize, "else adjust times_vte_scale"); - movl(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset())); + movl(scan_temp, Address(recv_klass, Klass::vtable_length_offset())); // %%% Could store the aligned, prescaled offset in the klassoop. lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); @@ -5865,7 +5865,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, void MacroAssembler::lookup_virtual_method(Register recv_klass, RegisterOrConstant vtable_index, Register method_result) { - const int base = in_bytes(InstanceKlass::vtable_start_offset()); + const int base = in_bytes(Klass::vtable_start_offset()); assert(vtableEntry::size() * wordSize == wordSize, "else adjust the scaling in the code below"); Address vtable_entry_addr(recv_klass, vtable_index, Address::times_ptr, diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp index f8029de59c1..3a5c7d0f38b 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp @@ -85,7 +85,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { if (DebugVtables) { Label L; // check offset vs vtable length - __ cmpl(Address(rax, InstanceKlass::vtable_length_offset()), vtable_index*vtableEntry::size()); + __ cmpl(Address(rax, Klass::vtable_length_offset()), vtable_index*vtableEntry::size()); __ jcc(Assembler::greater, L); __ movl(rbx, vtable_index); __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), rcx, rbx); diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp index f63e4c976e4..6c0a2fcb6af 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp @@ -77,7 +77,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { if (DebugVtables) { Label L; // check offset vs vtable length - __ cmpl(Address(rax, InstanceKlass::vtable_length_offset()), + __ cmpl(Address(rax, Klass::vtable_length_offset()), vtable_index * vtableEntry::size()); __ jcc(Assembler::greater, L); __ movl(rbx, vtable_index); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java index a411534ea3a..ddddbd8693e 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,6 @@ public class ArrayKlass extends Klass { dimension = new CIntField(type.getCIntegerField("_dimension"), 0); higherDimension = new MetadataField(type.getAddressField("_higher_dimension"), 0); lowerDimension = new MetadataField(type.getAddressField("_lower_dimension"), 0); - vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0); javaLangCloneableName = null; javaLangObjectName = null; javaIoSerializableName = null; @@ -61,7 +60,6 @@ public class ArrayKlass extends Klass { private static CIntField dimension; private static MetadataField higherDimension; private static MetadataField lowerDimension; - private static CIntField vtableLen; public Klass getJavaSuper() { SystemDictionary sysDict = VM.getVM().getSystemDictionary(); @@ -71,7 +69,6 @@ public class ArrayKlass extends Klass { public long getDimension() { return dimension.getValue(this); } public Klass getHigherDimension() { return (Klass) higherDimension.getValue(this); } public Klass getLowerDimension() { return (Klass) lowerDimension.getValue(this); } - public long getVtableLen() { return vtableLen.getValue(this); } // constant class names - javaLangCloneable, javaIoSerializable, javaLangObject // Initialized lazily to avoid initialization ordering dependencies between ArrayKlass and SymbolTable @@ -140,6 +137,5 @@ public class ArrayKlass extends Klass { visitor.doCInt(dimension, true); visitor.doMetadata(higherDimension, true); visitor.doMetadata(lowerDimension, true); - visitor.doCInt(vtableLen, true); } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 5369b11e101..d2f15f0c606 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -84,7 +84,6 @@ public class InstanceKlass extends Klass { nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0); isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0); initState = new CIntField(type.getCIntegerField("_init_state"), 0); - vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0); itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0); breakpoints = type.getAddressField("_breakpoints"); genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0); @@ -143,7 +142,6 @@ public class InstanceKlass extends Klass { private static CIntField nonstaticOopMapSize; private static CIntField isMarkedDependent; private static CIntField initState; - private static CIntField vtableLen; private static CIntField itableLen; private static AddressField breakpoints; private static CIntField genericSignatureIndex; @@ -351,7 +349,6 @@ public class InstanceKlass extends Klass { public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); } public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); } public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; } - public long getVtableLen() { return vtableLen.getValue(this); } public long getItableLen() { return itableLen.getValue(this); } public long majorVersion() { return majorVersion.getValue(this); } public long minorVersion() { return minorVersion.getValue(this); } @@ -547,7 +544,6 @@ public class InstanceKlass extends Klass { visitor.doCInt(nonstaticOopMapSize, true); visitor.doCInt(isMarkedDependent, true); visitor.doCInt(initState, true); - visitor.doCInt(vtableLen, true); visitor.doCInt(itableLen, true); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java index 3fe93b7fc6b..b5d93a852a7 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,6 +61,7 @@ public class Klass extends Metadata implements ClassConstants { } subklass = new MetadataField(type.getAddressField("_subklass"), 0); nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0); + vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0); LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue(); LH_LOG2_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("Klass::_lh_log2_element_size_shift").intValue(); @@ -71,6 +72,7 @@ public class Klass extends Metadata implements ClassConstants { LH_ARRAY_TAG_OBJ_VALUE = db.lookupIntConstant("Klass::_lh_array_tag_obj_value").intValue(); } + public Klass(Address addr) { super(addr); } @@ -91,6 +93,7 @@ public class Klass extends Metadata implements ClassConstants { private static MetadataField subklass; private static MetadataField nextSibling; private static sun.jvm.hotspot.types.Field traceIDField; + private static CIntField vtableLen; private Address getValue(AddressField field) { return addr.getAddressAt(field.getOffset()); @@ -111,6 +114,7 @@ public class Klass extends Metadata implements ClassConstants { public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); } public Klass getSubklassKlass() { return (Klass) subklass.getValue(this); } public Klass getNextSiblingKlass() { return (Klass) nextSibling.getValue(this); } + public long getVtableLen() { return vtableLen.getValue(this); } public long traceID() { if (traceIDField == null) return 0; @@ -179,6 +183,7 @@ public class Klass extends Metadata implements ClassConstants { visitor.doCInt(accessFlags, true); visitor.doMetadata(subklass, true); visitor.doMetadata(nextSibling, true); + visitor.doCInt(vtableLen, true); } public long getObjectSize() { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 7c55fa2e534..0708b377366 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -597,7 +597,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp } HotSpotVMConfig config = config(); final int vtableIndex = getVtableIndex((HotSpotResolvedObjectTypeImpl) resolved); - return config.instanceKlassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset; + return config.klassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset; } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 65d92b1d8fd..0dc87859b3e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -482,8 +482,8 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem /* Everything has the core vtable of java.lang.Object */ return config.baseVtableLength(); } - int result = UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize); - assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize; + int result = UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize); + assert result >= config.baseVtableLength() : UNSAFE.getInt(getMetaspaceKlass() + config.klassVtableLengthOffset) + " " + config.vtableEntrySize; return result; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 6c0fad919ab..ad1e6df6085 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -1030,8 +1030,8 @@ public class HotSpotVMConfig { @HotSpotVMField(name = "InstanceKlass::_init_state", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassInitStateOffset; @HotSpotVMField(name = "InstanceKlass::_constants", type = "ConstantPool*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassConstantsOffset; @HotSpotVMField(name = "InstanceKlass::_fields", type = "Array*", get = HotSpotVMField.Type.OFFSET) @Stable public int instanceKlassFieldsOffset; - @HotSpotVMField(name = "CompilerToVM::Data::InstanceKlass_vtable_start_offset", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int instanceKlassVtableStartOffset; - @HotSpotVMField(name = "CompilerToVM::Data::InstanceKlass_vtable_length_offset", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int instanceKlassVtableLengthOffset; + @HotSpotVMField(name = "CompilerToVM::Data::Klass_vtable_start_offset", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int klassVtableStartOffset; + @HotSpotVMField(name = "CompilerToVM::Data::Klass_vtable_length_offset", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int klassVtableLengthOffset; @HotSpotVMConstant(name = "InstanceKlass::linked") @Stable public int instanceKlassStateLinked; @HotSpotVMConstant(name = "InstanceKlass::fully_initialized") @Stable public int instanceKlassStateFullyInitialized; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index f67a1d89c65..30ae8f86e9f 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2972,7 +2972,7 @@ void LIRGenerator::do_Invoke(Invoke* x) { SharedRuntime::get_resolve_virtual_call_stub(), arg_list, info); } else { - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + x->vtable_index() * vtableEntry::size_in_bytes(); + int entry_offset = in_bytes(Klass::vtable_start_offset()) + x->vtable_index() * vtableEntry::size_in_bytes(); int vtable_offset = entry_offset + vtableEntry::method_offset_in_bytes(); __ call_virtual(target, receiver, result_register, vtable_offset, arg_list, info); } diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index 6926a77392a..4b1305bb6cf 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -121,8 +121,8 @@ extern uint64_t jvmciHotSpotVMAddressEntryValueOffset; extern uint64_t jvmciHotSpotVMAddressEntryArrayStride; } -int CompilerToVM::Data::InstanceKlass_vtable_start_offset; -int CompilerToVM::Data::InstanceKlass_vtable_length_offset; +int CompilerToVM::Data::Klass_vtable_start_offset; +int CompilerToVM::Data::Klass_vtable_length_offset; int CompilerToVM::Data::Method_extra_stack_entries; @@ -151,8 +151,8 @@ jbyte* CompilerToVM::Data::cardtable_start_address; int CompilerToVM::Data::cardtable_shift; void CompilerToVM::Data::initialize() { - InstanceKlass_vtable_start_offset = in_bytes(InstanceKlass::vtable_start_offset()); - InstanceKlass_vtable_length_offset = in_bytes(InstanceKlass::vtable_length_offset()); + Klass_vtable_start_offset = in_bytes(Klass::vtable_start_offset()); + Klass_vtable_length_offset = in_bytes(Klass::vtable_length_offset()); Method_extra_stack_entries = Method::extra_stack_entries(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp index 1947324556b..6ad1f3264a0 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,8 @@ class CompilerToVM { friend class JVMCIVMStructs; private: - static int InstanceKlass_vtable_start_offset; - static int InstanceKlass_vtable_length_offset; + static int Klass_vtable_start_offset; + static int Klass_vtable_length_offset; static int Method_extra_stack_entries; diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp index 84f7dca06ef..0d6e4639853 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * 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,8 +45,8 @@ #define VM_STRUCTS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field) \ - static_field(CompilerToVM::Data, InstanceKlass_vtable_start_offset, int) \ - static_field(CompilerToVM::Data, InstanceKlass_vtable_length_offset, int) \ + static_field(CompilerToVM::Data, Klass_vtable_start_offset, int) \ + static_field(CompilerToVM::Data, Klass_vtable_length_offset, int) \ \ static_field(CompilerToVM::Data, Method_extra_stack_entries, int) \ \ diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index f3e02874d7d..66a815ba942 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -81,10 +81,10 @@ Method* ArrayKlass::uncached_lookup_method(const Symbol* name, ArrayKlass::ArrayKlass(Symbol* name) : _dimension(1), _higher_dimension(NULL), - _lower_dimension(NULL), - // Arrays don't add any new methods, so their vtable is the same size as - // the vtable of klass Object. - _vtable_len(Universe::base_vtable_size()) { + _lower_dimension(NULL) { + // Arrays don't add any new methods, so their vtable is the same size as + // the vtable of klass Object. + set_vtable_length(Universe::base_vtable_size()); set_name(name); set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass()); set_layout_helper(Klass::_lh_neutral_value); diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 01faa793334..9f3ffb57064 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -39,7 +39,6 @@ class ArrayKlass: public Klass { int _dimension; // This is n'th-dimensional array. Klass* volatile _higher_dimension; // Refers the (n+1)'th-dimensional array (if present). Klass* volatile _lower_dimension; // Refers the (n-1)'th-dimensional array (if present). - int _vtable_len; // size of vtable for this klass protected: // Constructors @@ -112,9 +111,6 @@ class ArrayKlass: public Klass { // Java vtable klassVtable* vtable() const; // return new klassVtable - int vtable_length() const { return _vtable_len; } - static int base_vtable_length() { return Universe::base_vtable_size(); } - void set_vtable_length(int len) { assert(len == base_vtable_length(), "bad length"); _vtable_len = len; } protected: inline intptr_t* start_of_vtable() const; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 84a4c6edacf..5718da486ad 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -211,9 +211,9 @@ Array* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) { InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind) : _static_field_size(parser.static_field_size()), _nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())), - _vtable_len(parser.vtable_size()), _itable_len(parser.itable_size()), _reference_type(parser.reference_type()) { + set_vtable_length(parser.vtable_size()); set_kind(kind); set_access_flags(parser.access_flags()); set_is_anonymous(parser.is_anonymous()); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index d807aa2ce55..d96dfe917e0 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -178,6 +178,7 @@ class InstanceKlass: public Klass { u2 _java_fields_count; // The number of declared Java fields int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks + int _itable_len; // length of Java itable (in words) // _is_marked_dependent can be set concurrently, thus cannot be part of the // _misc_flags. bool _is_marked_dependent; // used for marking during flushing and deoptimization @@ -211,8 +212,6 @@ class InstanceKlass: public Klass { u2 _minor_version; // minor version number of class file u2 _major_version; // major version number of class file Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization) - int _vtable_len; // length of Java vtable (in words) - int _itable_len; // length of Java itable (in words) OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) MemberNameTable* _member_names; // Member names JNIid* _jni_ids; // First JNI identifier for static fields in this class @@ -311,10 +310,6 @@ class InstanceKlass: public Klass { int static_oop_field_count() const { return (int)_static_oop_field_count; } void set_static_oop_field_count(u2 size) { _static_oop_field_count = size; } - // Java vtable - int vtable_length() const { return _vtable_len; } - void set_vtable_length(int len) { _vtable_len = len; } - // Java itable int itable_length() const { return _itable_len; } void set_itable_length(int len) { _itable_len = len; } @@ -949,9 +944,6 @@ public: virtual void collect_statistics(KlassSizeStats *sz) const; #endif - static ByteSize vtable_start_offset() { return in_ByteSize(header_size() * wordSize); } - static ByteSize vtable_length_offset() { return byte_offset_of(InstanceKlass, _vtable_len); } - intptr_t* start_of_vtable() const { return (intptr_t*) ((address)this + in_bytes(vtable_start_offset())); } intptr_t* start_of_itable() const { return start_of_vtable() + vtable_length(); } int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; } diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index a9d660b8e13..959e51458ed 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -659,6 +659,10 @@ void Klass::oop_verify_on(oop obj, outputStream* st) { guarantee(obj->klass()->is_klass(), "klass field is not a klass"); } +ByteSize Klass::vtable_start_offset() { + return in_ByteSize(InstanceKlass::header_size() * wordSize); +} + #ifndef PRODUCT bool Klass::verify_vtable_index(int i) { diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 21616a01da1..ec34818617a 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -131,13 +131,16 @@ class Klass : public Metadata { jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. + TRACE_DEFINE_KLASS_TRACE_ID; + // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) jlong _last_biased_lock_bulk_revocation_time; markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; - TRACE_DEFINE_KLASS_TRACE_ID; + // vtable length + int _vtable_len; // Remembered sets support for the oops in the klasses. jbyte _modified_oops; // Card Table Equivalent (YC/CMS support) @@ -375,7 +378,7 @@ protected: // vtables virtual klassVtable* vtable() const = 0; - virtual int vtable_length() const = 0; + int vtable_length() const { return _vtable_len; } // subclass check bool is_subclass_of(const Klass* k) const; @@ -438,7 +441,14 @@ protected: virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS); virtual Klass* array_klass_impl(bool or_null, TRAPS); + void set_vtable_length(int len) { _vtable_len= len; } + public: + static ByteSize vtable_start_offset(); + static ByteSize vtable_length_offset() { + return byte_offset_of(Klass, _vtable_len); + } + // CDS support - remove and restore oops from metadata. Oops are not shared. virtual void remove_unshareable_info(); virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index cff1027c35d..9d6483248cc 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -3828,7 +3828,7 @@ Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "bad index %d", vtable_index); // Get the Method* out of the appropriate vtable entry. - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index*vtableEntry::size_in_bytes() + vtableEntry::method_offset_in_bytes(); Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 887b2b906f5..9893d96fd75 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -298,7 +298,6 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(ArrayKlass, _dimension, int) \ volatile_nonstatic_field(ArrayKlass, _higher_dimension, Klass*) \ volatile_nonstatic_field(ArrayKlass, _lower_dimension, Klass*) \ - nonstatic_field(ArrayKlass, _vtable_len, int) \ nonstatic_field(CompiledICHolder, _holder_method, Method*) \ nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \ nonstatic_field(ConstantPool, _tags, Array*) \ @@ -332,7 +331,6 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(InstanceKlass, _major_version, u2) \ nonstatic_field(InstanceKlass, _init_state, u1) \ nonstatic_field(InstanceKlass, _init_thread, Thread*) \ - nonstatic_field(InstanceKlass, _vtable_len, int) \ nonstatic_field(InstanceKlass, _itable_len, int) \ nonstatic_field(InstanceKlass, _reference_type, u1) \ volatile_nonstatic_field(InstanceKlass, _oop_map_cache, OopMapCache*) \ @@ -358,6 +356,7 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(Klass, _access_flags, AccessFlags) \ nonstatic_field(Klass, _prototype_header, markOop) \ nonstatic_field(Klass, _next_sibling, Klass*) \ + nonstatic_field(Klass, _vtable_len, int) \ nonstatic_field(vtableEntry, _method, Method*) \ nonstatic_field(MethodData, _size, int) \ nonstatic_field(MethodData, _method, Method*) \ diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp index 8072eaa1c56..2d274673b51 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp @@ -1144,7 +1144,7 @@ Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver, klass, SharkType::Method_type(), vtableEntry::size_in_bytes(), - InstanceKlass::vtable_start_offset(), + Klass::vtable_start_offset(), LLVMValue::intptr_constant(vtable_index)), "callee"); } @@ -1166,12 +1166,12 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, Value *vtable_start = builder()->CreateAdd( builder()->CreatePtrToInt(object_klass, SharkType::intptr_type()), LLVMValue::intptr_constant( - in_bytes(InstanceKlass::vtable_start_offset())), + in_bytes(Klass::vtable_start_offset())), "vtable_start"); Value *vtable_length = builder()->CreateValueOfStructEntry( object_klass, - InstanceKlass::vtable_length_offset(), + Klass::vtable_length_offset(), SharkType::jint_type(), "vtable_length"); vtable_length = From 3cda485fe5edf2cfa08025b3f72bfb58faa508df Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Tue, 19 Jan 2016 12:07:32 +0100 Subject: [PATCH 032/139] 8148481: Devirtualize Klass::vtable Move remainder of vtable related methods to Klass Reviewed-by: cjplummer, coleenp --- .../src/share/vm/interpreter/linkResolver.cpp | 12 ++++------ .../src/share/vm/jvmci/jvmciCompilerToVM.cpp | 8 ++----- hotspot/src/share/vm/oops/arrayKlass.cpp | 13 ----------- hotspot/src/share/vm/oops/arrayKlass.hpp | 7 ------ hotspot/src/share/vm/oops/cpCache.cpp | 6 ++--- hotspot/src/share/vm/oops/instanceKlass.cpp | 8 +++---- hotspot/src/share/vm/oops/instanceKlass.hpp | 22 ++++--------------- hotspot/src/share/vm/oops/klass.cpp | 18 +++++++++++++++ hotspot/src/share/vm/oops/klass.hpp | 6 ++++- hotspot/src/share/vm/prims/jni.cpp | 6 +---- hotspot/src/share/vm/runtime/reflection.cpp | 7 ++---- hotspot/src/share/vm/utilities/debug.cpp | 4 ++-- 12 files changed, 44 insertions(+), 73 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 80d44163ae3..defbf643c7f 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -168,7 +168,7 @@ CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) { } else if (!resolved_klass->is_interface()) { // A default or miranda method. Compute the vtable index. ResourceMark rm; - klassVtable* vt = InstanceKlass::cast(resolved_klass)->vtable(); + klassVtable* vt = resolved_klass->vtable(); index = LinkResolver::vtable_index_of_interface_method(resolved_klass, resolved_method); assert(index >= 0 , "we should have valid vtable index at this point"); @@ -1227,8 +1227,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, resolved_method); assert(vtable_index >= 0 , "we should have valid vtable index at this point"); - InstanceKlass* inst = InstanceKlass::cast(recv_klass()); - selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); + selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); } else { // at this point we are sure that resolved_method is virtual and not // a default or miranda method; therefore, it must have a valid vtable index. @@ -1243,10 +1242,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, assert(resolved_method->can_be_statically_bound(), "cannot override this method"); selected_method = resolved_method; } else { - // recv_klass might be an arrayKlassOop but all vtables start at - // the same place. The cast is to avoid virtual call and assertion. - InstanceKlass* inst = (InstanceKlass*)recv_klass(); - selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); + selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); } } diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index 4b1305bb6cf..cdb3ded801c 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -655,8 +655,7 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t vtable_index = LinkResolver::vtable_index_of_interface_method(holder_klass, resolved_method); assert(vtable_index >= 0 , "we should have valid vtable index at this point"); - InstanceKlass* inst = InstanceKlass::cast(recv_klass); - selected_method = inst->method_at_vtable(vtable_index); + selected_method = recv_klass->method_at_vtable(vtable_index); } else { // at this point we are sure that resolved_method is virtual and not // a miranda method; therefore, it must have a valid vtable index. @@ -671,10 +670,7 @@ C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_t assert(resolved_method->can_be_statically_bound(), "cannot override this method"); selected_method = resolved_method(); } else { - // recv_klass might be an arrayKlassOop but all vtables start at - // the same place. The cast is to avoid virtual call and assertion. - InstanceKlass* inst = (InstanceKlass*)recv_klass; - selected_method = inst->method_at_vtable(vtable_index); + selected_method = recv_klass->method_at_vtable(vtable_index); } } oop result = CompilerToVM::get_jvmci_method(selected_method, CHECK_NULL); diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 66a815ba942..e92df43076f 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -117,19 +117,6 @@ bool ArrayKlass::compute_is_subtype_of(Klass* k) { || k == SystemDictionary::Serializable_klass(); } - -inline intptr_t* ArrayKlass::start_of_vtable() const { - // all vtables start at the same place, that's why we use InstanceKlass::header_size here - return ((intptr_t*)this) + InstanceKlass::header_size(); -} - - -klassVtable* ArrayKlass::vtable() const { - KlassHandle kh(Thread::current(), this); - return new klassVtable(kh, start_of_vtable(), vtable_length() / vtableEntry::size()); -} - - objArrayOop ArrayKlass::allocate_arrayArray(int n, int length, TRAPS) { if (length < 0) { THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 9f3ffb57064..b98a092f735 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -98,7 +98,6 @@ class ArrayKlass: public Klass { bool compute_is_subtype_of(Klass* k); // Sizing - static int header_size() { return sizeof(ArrayKlass)/wordSize; } static int static_size(int header_size); #if INCLUDE_SERVICES @@ -109,12 +108,6 @@ class ArrayKlass: public Klass { } #endif - // Java vtable - klassVtable* vtable() const; // return new klassVtable - protected: - inline intptr_t* start_of_vtable() const; - - public: // Iterators void array_klasses_do(void f(Klass* k)); void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index 6066a319e8f..9218e2a439a 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -394,9 +394,7 @@ Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpo int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index()); if (cpool->tag_at(holder_index).is_klass()) { Klass* klass = cpool->resolved_klass_at(holder_index); - if (!klass->is_instance_klass()) - klass = SystemDictionary::Object_klass(); - return InstanceKlass::cast(klass)->method_at_vtable(f2_as_index()); + return klass->method_at_vtable(f2_as_index()); } } break; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 5718da486ad..1638f9dd508 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -364,10 +364,6 @@ bool InstanceKlass::should_be_initialized() const { return !is_initialized(); } -klassVtable* InstanceKlass::vtable() const { - return new klassVtable(this, start_of_vtable(), vtable_length() / vtableEntry::size()); -} - klassItable* InstanceKlass::itable() const { return new klassItable(instanceKlassHandle(this)); } @@ -2667,6 +2663,10 @@ static void print_vtable(intptr_t* start, int len, outputStream* st) { } } +static void print_vtable(vtableEntry* start, int len, outputStream* st) { + return print_vtable(reinterpret_cast(start), len, st); +} + void InstanceKlass::print_on(outputStream* st) const { assert(is_klass(), "must be klass"); Klass::print_on(st); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index d96dfe917e0..5c79ba530d9 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -944,11 +944,10 @@ public: virtual void collect_statistics(KlassSizeStats *sz) const; #endif - intptr_t* start_of_vtable() const { return (intptr_t*) ((address)this + in_bytes(vtable_start_offset())); } - intptr_t* start_of_itable() const { return start_of_vtable() + vtable_length(); } - int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; } + intptr_t* start_of_itable() const { return (intptr_t*)start_of_vtable() + vtable_length(); } + intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); } - intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); } + int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; } address static_field_addr(int offset); @@ -997,9 +996,7 @@ public: return !layout_helper_needs_slow_path(layout_helper()); } - // Java vtable/itable - klassVtable* vtable() const; // return new klassVtable wrapper - inline Method* method_at_vtable(int index); + // Java itable klassItable* itable() const; // return new klassItable wrapper Method* method_at_itable(Klass* holder, int index, TRAPS); @@ -1249,17 +1246,6 @@ public: void oop_verify_on(oop obj, outputStream* st); }; -inline Method* InstanceKlass::method_at_vtable(int index) { -#ifndef PRODUCT - assert(index >= 0, "valid vtable index"); - if (DebugVtables) { - verify_vtable_index(index); - } -#endif - vtableEntry* ve = (vtableEntry*)start_of_vtable(); - return ve[index].method(); -} - // for adding methods // UNSET_IDNUM return means no more ids available inline u2 InstanceKlass::next_method_idnum() { diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 959e51458ed..46d62102563 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -659,6 +659,24 @@ void Klass::oop_verify_on(oop obj, outputStream* st) { guarantee(obj->klass()->is_klass(), "klass field is not a klass"); } +klassVtable* Klass::vtable() const { + return new klassVtable(this, start_of_vtable(), vtable_length() / vtableEntry::size()); +} + +vtableEntry* Klass::start_of_vtable() const { + return (vtableEntry*) ((address)this + in_bytes(vtable_start_offset())); +} + +Method* Klass::method_at_vtable(int index) { +#ifndef PRODUCT + assert(index >= 0, "valid vtable index"); + if (DebugVtables) { + verify_vtable_index(index); + } +#endif + return start_of_vtable()[index].method(); +} + ByteSize Klass::vtable_start_offset() { return in_ByteSize(InstanceKlass::header_size() * wordSize); } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index ec34818617a..462ae43b52b 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -57,6 +57,7 @@ class ParCompactionManager; class PSPromotionManager; class KlassSizeStats; class fieldDescriptor; +class vtableEntry; class Klass : public Metadata { friend class VMStructs; @@ -377,7 +378,7 @@ protected: #endif // vtables - virtual klassVtable* vtable() const = 0; + klassVtable* vtable() const; int vtable_length() const { return _vtable_len; } // subclass check @@ -443,7 +444,10 @@ protected: void set_vtable_length(int len) { _vtable_len= len; } + vtableEntry* start_of_vtable() const; public: + Method* method_at_vtable(int index); + static ByteSize vtable_start_offset(); static ByteSize vtable_length_offset() { return byte_offset_of(Klass, _vtable_len); diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index e3251d14e56..d4808682944 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -1131,11 +1131,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive assert(m->valid_vtable_index(), "no valid vtable index"); int vtbl_index = m->vtable_index(); if (vtbl_index != Method::nonvirtual_vtable_index) { - Klass* k = h_recv->klass(); - // k might be an arrayKlassOop but all vtables start at - // the same place. The cast is to avoid virtual call and assertion. - InstanceKlass *ik = (InstanceKlass*)k; - selected_method = ik->method_at_vtable(vtbl_index); + selected_method = h_recv->klass()->method_at_vtable(vtbl_index); } else { // final method selected_method = m; diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 5c12e122566..7eda3c51393 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -939,10 +939,7 @@ static oop invoke(instanceKlassHandle klass, int index = reflected_method->vtable_index(); method = reflected_method; if (index != Method::nonvirtual_vtable_index) { - // target_klass might be an arrayKlassOop but all vtables start at - // the same place. The cast is to avoid virtual call and assertion. - InstanceKlass* inst = (InstanceKlass*)target_klass(); - method = methodHandle(THREAD, inst->method_at_vtable(index)); + method = methodHandle(THREAD, target_klass->method_at_vtable(index)); } if (!method.is_null()) { // Check for abstract methods as well diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index 29ccf223721..56a84a32ef2 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -461,7 +461,7 @@ extern "C" void blob(CodeBlob* cb) { extern "C" void dump_vtable(address p) { Command c("dump_vtable"); Klass* k = (Klass*)p; - InstanceKlass::cast(k)->vtable()->print(); + k->vtable()->print(); } From 722817ba99a1b54e4251211dbdf8a26d5b9d5538 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 29 Jan 2016 09:21:15 +0100 Subject: [PATCH 033/139] 8147510: [windows] no text locations shown for register info in hs-err file Reviewed-by: dholmes, iklam --- hotspot/src/os/windows/vm/os_windows.cpp | 27 ++++++++++++++++--- .../os_cpu/windows_x86/vm/os_windows_x86.cpp | 2 ++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index f0ab29c3486..1df102a7607 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5267,8 +5267,29 @@ bool os::check_heap(bool force) { bool os::find(address addr, outputStream* st) { - // Nothing yet - return false; + int offset = -1; + bool result = false; + char buf[256]; + if (os::dll_address_to_library_name(addr, buf, sizeof(buf), &offset)) { + st->print(PTR_FORMAT " ", addr); + if (strlen(buf) < sizeof(buf) - 1) { + char* p = strrchr(buf, '\\'); + if (p) { + st->print("%s", p + 1); + } else { + st->print("%s", buf); + } + } else { + // The library name is probably truncated. Let's omit the library name. + // See also JDK-8147512. + } + if (os::dll_address_to_function_name(addr, buf, sizeof(buf), &offset)) { + st->print("::%s + 0x%x", buf, offset); + } + st->cr(); + result = true; + } + return result; } LONG WINAPI os::win32::serialize_fault_filter(struct _EXCEPTION_POINTERS* e) { diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index ab6ba5c9037..284091dc09c 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -599,6 +599,7 @@ void os::print_register_info(outputStream *st, const void *context) { // this is only for the "general purpose" registers #ifdef AMD64 + st->print("RIP="); print_location(st, uc->Rip); st->print("RAX="); print_location(st, uc->Rax); st->print("RBX="); print_location(st, uc->Rbx); st->print("RCX="); print_location(st, uc->Rcx); @@ -616,6 +617,7 @@ void os::print_register_info(outputStream *st, const void *context) { st->print("R14="); print_location(st, uc->R14); st->print("R15="); print_location(st, uc->R15); #else + st->print("EIP="); print_location(st, uc->Eip); st->print("EAX="); print_location(st, uc->Eax); st->print("EBX="); print_location(st, uc->Ebx); st->print("ECX="); print_location(st, uc->Ecx); From 4bfa63dd3431853a82e83c5ba85881710d67a3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Lid=C3=A9n?= Date: Mon, 1 Feb 2016 22:11:16 +0100 Subject: [PATCH 034/139] 8147918: Rename develop_log_is_enabled() to log_develop_is_enabled() Reviewed-by: dholmes, brutisso --- hotspot/src/share/vm/gc/cms/parNewGeneration.cpp | 2 +- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 2 +- .../src/share/vm/gc/parallel/psParallelCompact.cpp | 14 +++++++------- .../share/vm/gc/parallel/psPromotionManager.cpp | 2 +- .../vm/gc/parallel/psPromotionManager.inline.hpp | 2 +- .../share/vm/interpreter/interpreterRuntime.cpp | 2 +- hotspot/src/share/vm/interpreter/linkResolver.cpp | 12 ++++++------ hotspot/src/share/vm/logging/log.hpp | 4 ++-- hotspot/src/share/vm/memory/metaspace.cpp | 4 ++-- hotspot/src/share/vm/oops/klassVtable.cpp | 14 +++++++------- 10 files changed, 29 insertions(+), 29 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp index 7dbdebe0f04..0f2f019e9d8 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp @@ -414,7 +414,7 @@ void ParScanThreadStateSet::print_taskqueue_stats_hdr(outputStream* const st) { } void ParScanThreadStateSet::print_taskqueue_stats() { - if (!develop_log_is_enabled(Trace, gc, task, stats)) { + if (!log_develop_is_enabled(Trace, gc, task, stats)) { return; } LogHandle(gc, task, stats) log; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 9faa2774b7e..900277928b6 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -3141,7 +3141,7 @@ void G1CollectedHeap::print_taskqueue_stats_hdr(outputStream* const st) { } void G1CollectedHeap::print_taskqueue_stats() const { - if (!develop_log_is_enabled(Trace, gc, task, stats)) { + if (!log_develop_is_enabled(Trace, gc, task, stats)) { return; } LogHandle(gc, task, stats) log; diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index 473610c1b1f..b841c32e494 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -195,7 +195,7 @@ const char* PSParallelCompact::space_names[] = { }; void PSParallelCompact::print_region_ranges() { - if (!develop_log_is_enabled(Trace, gc, compaction, phases)) { + if (!log_develop_is_enabled(Trace, gc, compaction, phases)) { return; } LogHandle(gc, compaction, phases) log; @@ -265,7 +265,7 @@ void print_generic_summary_data(ParallelCompactData& summary_data, SpaceInfo* space_info) { - if (!develop_log_is_enabled(Trace, gc, compaction, phases)) { + if (!log_develop_is_enabled(Trace, gc, compaction, phases)) { return; } @@ -360,7 +360,7 @@ print_initial_summary_data(ParallelCompactData& summary_data, void print_initial_summary_data(ParallelCompactData& summary_data, SpaceInfo* space_info) { - if (!develop_log_is_enabled(Trace, gc, compaction, phases)) { + if (!log_develop_is_enabled(Trace, gc, compaction, phases)) { return; } @@ -641,7 +641,7 @@ ParallelCompactData::summarize_split_space(size_t src_region, *target_next = split_destination + partial_obj_size; HeapWord* const source_next = region_to_addr(split_region) + partial_obj_size; - if (develop_log_is_enabled(Trace, gc, compaction, phases)) { + if (log_develop_is_enabled(Trace, gc, compaction, phases)) { const char * split_type = partial_obj_size == 0 ? "easy" : "hard"; log_develop_trace(gc, compaction, phases)("%s split: src=" PTR_FORMAT " src_c=" SIZE_FORMAT " pos=" SIZE_FORMAT, split_type, p2i(source_next), split_region, partial_obj_size); @@ -1535,7 +1535,7 @@ PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction) } } - if (develop_log_is_enabled(Trace, gc, compaction, phases)) { + if (log_develop_is_enabled(Trace, gc, compaction, phases)) { const size_t region_size = ParallelCompactData::RegionSize; HeapWord* const dense_prefix_end = _space_info[id].dense_prefix(); const size_t dp_region = _summary_data.addr_to_region_idx(dense_prefix_end); @@ -2190,7 +2190,7 @@ private: bool _enabled; size_t _total_regions; public: - FillableRegionLogger() : _next_index(0), _total_regions(0), _enabled(develop_log_is_enabled(Trace, gc, compaction)) { } + FillableRegionLogger() : _next_index(0), _total_regions(0), _enabled(log_develop_is_enabled(Trace, gc, compaction)) { } ~FillableRegionLogger() { log.trace(SIZE_FORMAT " initially fillable regions", _total_regions); } @@ -2381,7 +2381,7 @@ void PSParallelCompact::enqueue_region_stealing_tasks( // region. void PSParallelCompact::write_block_fill_histogram() { - if (!develop_log_is_enabled(Trace, gc, compaction)) { + if (!log_develop_is_enabled(Trace, gc, compaction)) { return; } diff --git a/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp b/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp index fce698b6ee1..a147cd77ad3 100644 --- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp +++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.cpp @@ -130,7 +130,7 @@ static const char* const pm_stats_hdr[] = { void PSPromotionManager::print_taskqueue_stats() { - if (!develop_log_is_enabled(Trace, gc, task, stats)) { + if (!log_develop_is_enabled(Trace, gc, task, stats)) { return; } LogHandle(gc, task, stats) log; diff --git a/hotspot/src/share/vm/gc/parallel/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc/parallel/psPromotionManager.inline.hpp index 2b6ac4a595c..b6e3a6e7b63 100644 --- a/hotspot/src/share/vm/gc/parallel/psPromotionManager.inline.hpp +++ b/hotspot/src/share/vm/gc/parallel/psPromotionManager.inline.hpp @@ -284,7 +284,7 @@ inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) { // This code must come after the CAS test, or it will print incorrect // information. - if (develop_log_is_enabled(Trace, gc, scavenge) && o->is_forwarded()) { + if (log_develop_is_enabled(Trace, gc, scavenge) && o->is_forwarded()) { log_develop_trace(gc, scavenge)("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", "forwarding", new_obj->klass()->internal_name(), p2i((void *)o), p2i((void *)new_obj), new_obj->size()); diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index a77328198cd..914492f32d9 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -763,7 +763,7 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte if (cp_cache_entry->is_resolved(bytecode)) return; if (bytecode == Bytecodes::_invokeinterface) { - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { ResourceMark rm(thread); log_develop_trace(itables)("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index defbf643c7f..71f3beb4387 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -816,7 +816,7 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokeinterface resolved method: caller-class", link_info.current_klass(), resolved_klass, resolved_method, true); @@ -1064,7 +1064,7 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokespecial resolved method: caller-class:", current_klass, resolved_klass, resolved_method, true); } @@ -1135,7 +1135,7 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, sel_method->signature())); } - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokespecial selected method: resolved-class:", resolved_klass, resolved_klass, sel_method, true); } @@ -1188,7 +1188,7 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { trace_method_resolution("invokevirtual resolved method: caller-class:", current_klass, resolved_klass, resolved_method, false); } @@ -1264,7 +1264,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, selected_method->signature())); } - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { trace_method_resolution("invokevirtual selected method: receiver-class:", recv_klass, resolved_klass, selected_method, false, vtable_index); @@ -1363,7 +1363,7 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, sel_method->signature())); } - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokeinterface selected method: receiver-class", recv_klass, resolved_klass, sel_method, true); } diff --git a/hotspot/src/share/vm/logging/log.hpp b/hotspot/src/share/vm/logging/log.hpp index 5c6b008f569..722b2d3af90 100644 --- a/hotspot/src/share/vm/logging/log.hpp +++ b/hotspot/src/share/vm/logging/log.hpp @@ -57,13 +57,13 @@ #define log_develop_info(...) (!log_is_enabled(Info, __VA_ARGS__)) ? (void)0 : Log::write #define log_develop_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : Log::write #define log_develop_trace(...) (!log_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : Log::write -#define develop_log_is_enabled(level, ...) log_is_enabled(level, __VA_ARGS__) +#define log_develop_is_enabled(level, ...) log_is_enabled(level, __VA_ARGS__) #else #define DUMMY_ARGUMENT_CONSUMER(...) #define log_develop_info(...) DUMMY_ARGUMENT_CONSUMER #define log_develop_debug(...) DUMMY_ARGUMENT_CONSUMER #define log_develop_trace(...) DUMMY_ARGUMENT_CONSUMER -#define develop_log_is_enabled(...) false +#define log_develop_is_enabled(...) false #endif // Convenience macro to test if the logging is enabled on the specified level for given tags. diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 39b8c2c5917..db821792528 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1234,7 +1234,7 @@ void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry) { #ifdef ASSERT new_entry->mangle(); #endif - if (develop_log_is_enabled(Trace, gc, metaspace)) { + if (log_develop_is_enabled(Trace, gc, metaspace)) { LogHandle(gc, metaspace) log; VirtualSpaceNode* vsl = current_virtual_space(); ResourceMark rm; @@ -3051,7 +3051,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a initialize_class_space(metaspace_rs); - if (develop_log_is_enabled(Trace, gc, metaspace)) { + if (log_develop_is_enabled(Trace, gc, metaspace)) { LogHandle(gc, metaspace) log; ResourceMark rm; print_compressed_class_space(log.trace_stream(), requested_addr); diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 090e5e8b9c5..13e6fbadfa9 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -135,7 +135,7 @@ int klassVtable::initialize_from_super(KlassHandle super) { superVtable->verify(tty, true); #endif superVtable->copy_vtable_to(table()); - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm; log_develop_trace(vtables)("copy vtable from %s to %s size %d", super->internal_name(), klass()->internal_name(), @@ -272,7 +272,7 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch"); #endif if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) { - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm(THREAD); outputStream* logst = LogHandle(vtables)::trace_stream(); char* sig = target_method()->name_and_sig_as_C_string(); @@ -303,7 +303,7 @@ static void log_vtables(int i, bool overrides, methodHandle target_method, KlassHandle target_klass, Method* super_method, Thread* thread) { #ifndef PRODUCT - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm(thread); outputStream* logst = LogHandle(vtables)::trace_stream(); char* sig = target_method()->name_and_sig_as_C_string(); @@ -491,7 +491,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar } void klassVtable::put_method_at(Method* m, int index) { - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm; outputStream* logst = LogHandle(vtables)::trace_stream(); const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : ""; @@ -818,7 +818,7 @@ int klassVtable::fill_in_mirandas(int initialized) { get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(), ik()->default_methods(), ik()->local_interfaces()); for (int i = 0; i < mirandas.length(); i++) { - if (develop_log_is_enabled(Trace, vtables)) { + if (log_develop_is_enabled(Trace, vtables)) { Method* meth = mirandas.at(i); ResourceMark rm(Thread::current()); outputStream* logst = LogHandle(vtables)::trace_stream(); @@ -1043,7 +1043,7 @@ int klassItable::assign_itable_indices_for_interface(Klass* klass) { if (interface_method_needs_itable_index(m)) { assert(!m->is_final_method(), "no final interface methods"); // If m is already assigned a vtable index, do not disturb it. - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { ResourceMark rm; outputStream* logst = LogHandle(itables)::trace_stream(); assert(m != NULL, "methods can never be null"); @@ -1158,7 +1158,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass int ime_num = m->itable_index(); assert(ime_num < ime_count, "oob"); itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target()); - if (develop_log_is_enabled(Trace, itables)) { + if (log_develop_is_enabled(Trace, itables)) { ResourceMark rm(THREAD); if (target() != NULL) { outputStream* logst = LogHandle(itables)::trace_stream(); From 2053203d5dcabb6d85fd01284c9bd453f1a36c42 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 1 Feb 2016 20:39:17 -0500 Subject: [PATCH 035/139] 8148771: os::active_processor_count() returns garbage which causes VM to crash Reviewed-by: kbarrett --- hotspot/src/share/vm/gc/g1/concurrentMark.cpp | 6 +++--- hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp index 69d6ca11eaa..a7c70b9483e 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -489,11 +489,11 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / (double) GCPauseIntervalMillis; - double cpu_ratio = 1.0 / (double) os::active_processor_count(); + double cpu_ratio = 1.0 / (double) os::processor_count(); double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); double marking_task_overhead = overall_cm_overhead / marking_thread_num * - (double) os::active_processor_count(); + (double) os::processor_count(); double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index b7dbd9e88b8..155faa0be5a 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -160,7 +160,7 @@ DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : // Determines how many mutator threads can process the buffers in parallel. uint DirtyCardQueueSet::num_par_ids() { - return (uint)os::active_processor_count(); + return (uint)os::processor_count(); } void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, From de76c23ff5817d028854a4b93c3e55d2d246c03c Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Tue, 2 Feb 2016 09:51:24 +0100 Subject: [PATCH 036/139] 8147913: Some runtime/CompressedOops tests fail on ARM64 product builds Reviewed-by: jmasa, kbarrett --- hotspot/src/share/vm/memory/metaspace.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index db821792528..72ec52da3d1 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1234,7 +1234,7 @@ void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry) { #ifdef ASSERT new_entry->mangle(); #endif - if (log_develop_is_enabled(Trace, gc, metaspace)) { + if (log_is_enabled(Trace, gc, metaspace)) { LogHandle(gc, metaspace) log; VirtualSpaceNode* vsl = current_virtual_space(); ResourceMark rm; @@ -3051,7 +3051,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a initialize_class_space(metaspace_rs); - if (log_develop_is_enabled(Trace, gc, metaspace)) { + if (log_is_enabled(Trace, gc, metaspace)) { LogHandle(gc, metaspace) log; ResourceMark rm; print_compressed_class_space(log.trace_stream(), requested_addr); From a5e2b096bc20ae7b67d48e671c39e3fcbc0afa61 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Tue, 2 Feb 2016 10:50:08 +0100 Subject: [PATCH 037/139] 8148734: G1: Make G1GCPhaseTimes keep track of the start GC time Reviewed-by: sjohanss, tschatzl --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 8 +++----- hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp | 2 +- hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp | 2 +- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 7 +++++-- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp | 4 +++- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 900277928b6..26d8b089e7e 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -3169,13 +3169,12 @@ void G1CollectedHeap::reset_taskqueue_stats() { } #endif // TASKQUEUE_STATS -void G1CollectedHeap::log_gc_footer(jlong pause_time_counter) { +void G1CollectedHeap::log_gc_footer() { if (evacuation_failed()) { log_info(gc)("To-space exhausted"); } - double pause_time_ms = TimeHelper::counter_to_millis(pause_time_counter); - g1_policy()->print_phases(pause_time_ms); + g1_policy()->print_phases(); g1_policy()->print_detailed_heap_transition(); } @@ -3267,7 +3266,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true); - jlong pause_start_counter = os::elapsed_counter(); g1_policy()->note_gc_start(active_workers); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); @@ -3529,7 +3527,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } // Print the remainder of the GC log output. - log_gc_footer(os::elapsed_counter() - pause_start_counter); + log_gc_footer(); // It is not yet to safe to tell the concurrent mark to // start as we have some optional output below. We don't want the diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 05cde22e58d..c5c8118c0a5 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -291,7 +291,7 @@ private: size_t size, size_t translation_factor); - void log_gc_footer(jlong pause_time_counter); + void log_gc_footer(); void trace_heap(GCWhen::Type when, const GCTracer* tracer); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index df6e8ffbfac..d0be1cef504 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -1303,8 +1303,8 @@ void G1CollectorPolicy::print_detailed_heap_transition() const { MetaspaceAux::print_metaspace_change(_metaspace_used_bytes_before_gc); } -void G1CollectorPolicy::print_phases(double pause_time_ms) { - phase_times()->print(pause_time_ms); +void G1CollectorPolicy::print_phases() { + phase_times()->print(); } void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index 530eddb8f74..c2ffcb78431 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -662,7 +662,7 @@ public: void print_detailed_heap_transition() const; - virtual void print_phases(double pause_time_ms); + virtual void print_phases(); void record_stop_world_start(); void record_concurrent_pause(); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index 0e5bb47b495..706495fdbc7 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -30,6 +30,7 @@ #include "gc/g1/workerDataArray.inline.hpp" #include "memory/allocation.hpp" #include "logging/log.hpp" +#include "runtime/timer.hpp" #include "runtime/os.hpp" // Helper class for avoiding interleaved logging @@ -133,6 +134,7 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { assert(active_gc_threads > 0, "The number of threads must be > 0"); assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads"); + _gc_start_counter = os::elapsed_counter(); _active_gc_threads = active_gc_threads; _cur_expand_heap_time_ms = 0.0; _external_accounted_time_ms = 0.0; @@ -146,6 +148,7 @@ void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { } void G1GCPhaseTimes::note_gc_end() { + _gc_pause_time_ms = TimeHelper::counter_to_millis(os::elapsed_counter() - _gc_start_counter); for (uint i = 0; i < _active_gc_threads; i++) { double worker_time = _gc_par_phases[GCWorkerEnd]->get(i) - _gc_par_phases[GCWorkerStart]->get(i); record_time_secs(GCWorkerTotal, i , worker_time); @@ -349,7 +352,7 @@ class G1GCParPhasePrinter : public StackObj { } }; -void G1GCPhaseTimes::print(double pause_time_ms) { +void G1GCPhaseTimes::print() { note_gc_end(); G1GCParPhasePrinter par_phase_printer(this); @@ -373,7 +376,7 @@ void G1GCPhaseTimes::print(double pause_time_ms) { } print_stats(Indents[1], "Clear CT", _cur_clear_ct_time_ms); print_stats(Indents[1], "Expand Heap After Collection", _cur_expand_heap_time_ms); - double misc_time_ms = pause_time_ms - accounted_time_ms(); + double misc_time_ms = _gc_pause_time_ms - accounted_time_ms(); print_stats(Indents[1], "Other", misc_time_ms); if (_cur_verify_before_time_ms > 0.0) { print_stats(Indents[2], "Verify Before", _cur_verify_before_time_ms); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index 1e4b166459a..5607c3f4ea0 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -36,6 +36,8 @@ class G1GCPhaseTimes : public CHeapObj { uint _active_gc_threads; uint _max_gc_threads; + jlong _gc_start_counter; + double _gc_pause_time_ms; public: enum GCParPhases { @@ -126,7 +128,7 @@ class G1GCPhaseTimes : public CHeapObj { public: G1GCPhaseTimes(uint max_gc_threads); void note_gc_start(uint active_gc_threads); - void print(double pause_time_ms); + void print(); // record the time a phase took in seconds void record_time_secs(GCParPhases phase, uint worker_i, double secs); From 636b10604f2b6260e326e29c63c98f1f354b29a7 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Tue, 2 Feb 2016 11:09:21 +0100 Subject: [PATCH 038/139] 8148053: Remove unused log tags Reviewed-by: dholmes, mlarsson, sla --- hotspot/src/share/vm/logging/logTag.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 5777c7a8b99..d4ff40bd0dd 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -42,7 +42,6 @@ LOG_TAG(classload) /* Trace all classes loaded */ \ LOG_TAG(classloaderdata) /* class loader loader_data lifetime */ \ LOG_TAG(classunload) /* Trace unloading of classes */ \ - LOG_TAG(comp) \ LOG_TAG(compaction) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ @@ -70,7 +69,6 @@ LOG_TAG(refine) \ LOG_TAG(region) \ LOG_TAG(remset) \ - LOG_TAG(rt) \ LOG_TAG(safepoint) \ LOG_TAG(scavenge) \ LOG_TAG(scrub) \ @@ -79,7 +77,6 @@ LOG_TAG(stats) \ LOG_TAG(stringdedup) \ LOG_TAG(survivor) \ - LOG_TAG(svc) \ LOG_TAG(sweep) \ LOG_TAG(task) \ LOG_TAG(tlab) \ From 69088591f9586b106b879ae0d7ab8da73c8d95aa Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 2 Feb 2016 05:38:33 -0500 Subject: [PATCH 039/139] 8148766: Test AvailableProcessors.java got wrong number of processors Reviewed-by: dsamersoff, tschatzl, mseledtsov --- hotspot/test/runtime/os/AvailableProcessors.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/test/runtime/os/AvailableProcessors.java b/hotspot/test/runtime/os/AvailableProcessors.java index 4188a11d914..529f2a0889b 100644 --- a/hotspot/test/runtime/os/AvailableProcessors.java +++ b/hotspot/test/runtime/os/AvailableProcessors.java @@ -27,7 +27,7 @@ import java.util.ArrayList; /* * @test - * @bug 6515172 + * @bug 6515172 8148766 * @summary Check that availableProcessors reports the correct value when running in a cpuset on linux * @requires os.family == "linux" * @library /testlibrary @@ -93,7 +93,9 @@ public class AvailableProcessors { static void checkProcessors(int expected) { int available = Runtime.getRuntime().availableProcessors(); - if (available != expected) + // available can dynamically drop below expected due to aggressive power management + // but we should never have more than expected, else taskset is broken + if (available <= 0 || available > expected) throw new Error("Expected " + expected + " processors, but found " + available); else From 0e9273e8a7f1356ca8becd19f62300d1c3a8b4ad Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Tue, 2 Feb 2016 12:12:17 +0100 Subject: [PATCH 040/139] 8148733: G1: Add log message to print the heap region size Reviewed-by: sjohanss, david --- hotspot/src/share/vm/gc/g1/heapRegion.cpp | 1 + .../test/gc/logging/TestDeprecatedPrintFlags.java | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 8ade4641c36..3c52afb166f 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -143,6 +143,7 @@ void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_hea // The cast to int is safe, given that we've bounded region_size by // MIN_REGION_SIZE and MAX_REGION_SIZE. GrainBytes = region_size; + log_info(gc, heap)("Heap region size: " SIZE_FORMAT "M", GrainBytes / M); guarantee(GrainWords == 0, "we should only set it once"); GrainWords = GrainBytes >> LogHeapWordSize; diff --git a/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java b/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java index a9ac87a5255..aaf4d5cff8d 100644 --- a/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java +++ b/hotspot/test/gc/logging/TestDeprecatedPrintFlags.java @@ -45,7 +45,7 @@ public class TestDeprecatedPrintFlags { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("-XX:+PrintGC is deprecated. Will use -Xlog:gc instead."); output.shouldNotContain("PrintGCDetails"); - output.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldMatch("\\[info.*\\]\\[gc *\\]"); output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); output.shouldHaveExitValue(0); } @@ -55,7 +55,7 @@ public class TestDeprecatedPrintFlags { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); output.shouldNotContain("PrintGC is deprecated"); - output.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldMatch("\\[info.*\\]\\[gc *\\]"); output.stdoutShouldMatch("\\[info.*\\]\\[gc\\,"); output.shouldHaveExitValue(0); } @@ -67,13 +67,13 @@ public class TestDeprecatedPrintFlags { output.shouldContain("-Xloggc is deprecated. Will use -Xlog:gc:gc-test.log instead."); output.shouldNotContain("PrintGCDetails"); output.shouldNotContain("PrintGC"); - output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc *\\]"); output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); output.shouldHaveExitValue(0); String lines = Files.lines(Paths.get(fileName)).collect(Collectors.joining()); System.out.println("lines: " + lines); OutputAnalyzer outputLog = new OutputAnalyzer(lines, ""); - outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc *\\]"); outputLog.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); } @@ -84,12 +84,12 @@ public class TestDeprecatedPrintFlags { output.shouldContain("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); output.shouldContain("-Xloggc is deprecated. Will use -Xlog:gc:gc-test.log instead."); output.shouldNotContain("PrintGC is deprecated"); - output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\]"); + output.stdoutShouldNotMatch("\\[info.*\\]\\[gc *\\]"); output.stdoutShouldNotMatch("\\[info.*\\]\\[gc\\,"); output.shouldHaveExitValue(0); String lines = Files.lines(Paths.get(fileName)).collect(Collectors.joining()); OutputAnalyzer outputLog = new OutputAnalyzer(lines, ""); - outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc\\]"); + outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc *\\]"); outputLog.stdoutShouldMatch("\\[info.*\\]\\[gc\\,"); } From f4f5e64f5dd0b6b250f1a5f0e242084f450a1d90 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Tue, 2 Feb 2016 12:13:05 +0100 Subject: [PATCH 041/139] 8148736: Let the G1 heap transition log regions instead of bytes Reviewed-by: sjohanss, david --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 39 +++--- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 2 - .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 59 +-------- .../src/share/vm/gc/g1/g1CollectorPolicy.hpp | 24 +--- .../src/share/vm/gc/g1/g1HeapTransition.cpp | 122 ++++++++++++++++++ .../src/share/vm/gc/g1/g1HeapTransition.hpp | 52 ++++++++ 6 files changed, 200 insertions(+), 98 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp create mode 100644 hotspot/src/share/vm/gc/g1/g1HeapTransition.hpp diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 26d8b089e7e..142758272f3 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -38,6 +38,7 @@ #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" +#include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1MarkSweep.hpp" #include "gc/g1/g1OopClosures.inline.hpp" @@ -1250,6 +1251,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, TraceCollectorStats tcs(g1mm()->full_collection_counters()); TraceMemoryManagerStats tms(true /* fullGC */, gc_cause()); + G1HeapTransition heap_transition(this); g1_policy()->record_full_collection_start(); // Note: When we have a more flexible GC logging framework that @@ -1442,15 +1444,15 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, g1mm()->update_sizes(); gc_epilogue(true); + + heap_transition.print(); + + print_heap_after_gc(); + trace_heap_after_gc(gc_tracer); + + post_full_gc_dump(gc_timer); } - g1_policy()->print_detailed_heap_transition(); - - print_heap_after_gc(); - trace_heap_after_gc(gc_tracer); - - post_full_gc_dump(gc_timer); - gc_timer->register_gc_end(); gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); } @@ -3169,17 +3171,6 @@ void G1CollectedHeap::reset_taskqueue_stats() { } #endif // TASKQUEUE_STATS -void G1CollectedHeap::log_gc_footer() { - if (evacuation_failed()) { - log_info(gc)("To-space exhausted"); - } - - g1_policy()->print_phases(); - - g1_policy()->print_detailed_heap_transition(); -} - - void G1CollectedHeap::wait_for_root_region_scanning() { double scan_wait_start = os::elapsedTime(); // We have to wait until the CM threads finish scanning the @@ -3281,6 +3272,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { append_secondary_free_list_if_not_empty_with_lock(); } + G1HeapTransition heap_transition(this); + size_t heap_used_bytes_before_gc = used(); + assert(check_young_list_well_formed(), "young list should be well formed"); // Don't dynamically change the number of GC threads this early. A value of @@ -3474,7 +3468,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { double sample_end_time_sec = os::elapsedTime(); double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS; size_t total_cards_scanned = per_thread_states.total_cards_scanned(); - g1_policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned); + g1_policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc); evacuation_info.set_collectionset_used_before(g1_policy()->collection_set_bytes_used_before()); evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc()); @@ -3527,7 +3521,12 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } // Print the remainder of the GC log output. - log_gc_footer(); + if (evacuation_failed()) { + log_info(gc)("To-space exhausted"); + } + + g1_policy()->print_phases(); + heap_transition.print(); // It is not yet to safe to tell the concurrent mark to // start as we have some optional output below. We don't want the diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index c5c8118c0a5..5e8ba970d18 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -291,8 +291,6 @@ private: size_t size, size_t translation_factor); - void log_gc_footer(); - void trace_heap(GCWhen::Type when, const GCTracer* tracer); void process_weak_jni_handles(); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index d0be1cef504..815990c5628 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -117,15 +117,6 @@ G1CollectorPolicy::G1CollectorPolicy() : _rs_lengths_prediction(0), _max_survivor_regions(0), - _eden_used_bytes_before_gc(0), - _survivor_used_bytes_before_gc(0), - _old_used_bytes_before_gc(0), - _humongous_used_bytes_before_gc(0), - _heap_used_bytes_before_gc(0), - _metaspace_used_bytes_before_gc(0), - _eden_capacity_bytes_before_gc(0), - _heap_capacity_bytes_before_gc(0), - _eden_cset_region_length(0), _survivor_cset_region_length(0), _old_cset_region_length(0), @@ -809,7 +800,6 @@ G1CollectorPolicy::verify_young_ages(HeapRegion* head, void G1CollectorPolicy::record_full_collection_start() { _full_collection_start_sec = os::elapsedTime(); - record_heap_size_info_at_start(true /* full */); // Release the future to-space so that it is available for compaction into. collector_state()->set_full_collection(true); } @@ -871,8 +861,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) { _trace_young_gen_time_data.record_start_collection(s_w_t_ms); _stop_world_start = 0.0; - record_heap_size_info_at_start(false /* full */); - phase_times()->record_cur_collection_start_sec(start_time_sec); _pending_cards = _g1->pending_card_num(); @@ -987,7 +975,7 @@ bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc // Anything below that is considered to be zero #define MIN_TIMER_GRANULARITY 0.0000001 -void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned) { +void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc) { double end_time_sec = os::elapsedTime(); size_t cur_used_bytes = _g1->used(); @@ -1138,7 +1126,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t } _rs_length_diff_seq->add((double) rs_length_diff); - size_t freed_bytes = _heap_used_bytes_before_gc - cur_used_bytes; + size_t freed_bytes = heap_used_bytes_before_gc - cur_used_bytes; size_t copied_bytes = _collection_set_bytes_used_before - freed_bytes; double cost_per_byte_ms = 0.0; @@ -1260,49 +1248,6 @@ void G1CollectorPolicy::report_ihop_statistics() { _ihop_control->print(); } -#define EXT_SIZE_FORMAT "%.1f%s" -#define EXT_SIZE_PARAMS(bytes) \ - byte_size_in_proper_unit((double)(bytes)), \ - proper_unit_for_byte_size((bytes)) - -void G1CollectorPolicy::record_heap_size_info_at_start(bool full) { - YoungList* young_list = _g1->young_list(); - _eden_used_bytes_before_gc = young_list->eden_used_bytes(); - _survivor_used_bytes_before_gc = young_list->survivor_used_bytes(); - _heap_capacity_bytes_before_gc = _g1->capacity(); - _old_used_bytes_before_gc = _g1->old_regions_count() * HeapRegion::GrainBytes; - _humongous_used_bytes_before_gc = _g1->humongous_regions_count() * HeapRegion::GrainBytes; - _heap_used_bytes_before_gc = _g1->used(); - _eden_capacity_bytes_before_gc = (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc; - _metaspace_used_bytes_before_gc = MetaspaceAux::used_bytes(); -} - -void G1CollectorPolicy::print_detailed_heap_transition() const { - YoungList* young_list = _g1->young_list(); - - size_t eden_used_bytes_after_gc = young_list->eden_used_bytes(); - size_t survivor_used_bytes_after_gc = young_list->survivor_used_bytes(); - size_t heap_used_bytes_after_gc = _g1->used(); - size_t old_used_bytes_after_gc = _g1->old_regions_count() * HeapRegion::GrainBytes; - size_t humongous_used_bytes_after_gc = _g1->humongous_regions_count() * HeapRegion::GrainBytes; - - size_t heap_capacity_bytes_after_gc = _g1->capacity(); - size_t eden_capacity_bytes_after_gc = - (_young_list_target_length * HeapRegion::GrainBytes) - survivor_used_bytes_after_gc; - size_t survivor_capacity_bytes_after_gc = _max_survivor_regions * HeapRegion::GrainBytes; - - log_info(gc, heap)("Eden: " SIZE_FORMAT "K->" SIZE_FORMAT "K(" SIZE_FORMAT "K)", - _eden_used_bytes_before_gc / K, eden_used_bytes_after_gc /K, eden_capacity_bytes_after_gc /K); - log_info(gc, heap)("Survivor: " SIZE_FORMAT "K->" SIZE_FORMAT "K(" SIZE_FORMAT "K)", - _survivor_used_bytes_before_gc / K, survivor_used_bytes_after_gc /K, survivor_capacity_bytes_after_gc /K); - log_info(gc, heap)("Old: " SIZE_FORMAT "K->" SIZE_FORMAT "K", - _old_used_bytes_before_gc / K, old_used_bytes_after_gc /K); - log_info(gc, heap)("Humongous: " SIZE_FORMAT "K->" SIZE_FORMAT "K", - _humongous_used_bytes_before_gc / K, humongous_used_bytes_after_gc /K); - - MetaspaceAux::print_metaspace_change(_metaspace_used_bytes_before_gc); -} - void G1CollectorPolicy::print_phases() { phase_times()->print(); } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index c2ffcb78431..5df6fcdaaeb 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -636,7 +636,7 @@ public: // Record the start and end of an evacuation pause. void record_collection_pause_start(double start_time_sec); - void record_collection_pause_end(double pause_time_ms, size_t cards_scanned); + void record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc); // Record the start and end of a full collection. void record_full_collection_start(); @@ -654,14 +654,6 @@ public: void record_concurrent_mark_cleanup_end(); void record_concurrent_mark_cleanup_completed(); - // Records the information about the heap size for reporting in - // print_detailed_heap_transition - void record_heap_size_info_at_start(bool full); - - // Print heap sizing transition (with less and more detail). - - void print_detailed_heap_transition() const; - virtual void print_phases(); void record_stop_world_start(); @@ -825,16 +817,6 @@ private: // The value of _heap_bytes_before_gc is also used to calculate // the cost of copying. - size_t _eden_used_bytes_before_gc; // Eden occupancy before GC - size_t _survivor_used_bytes_before_gc; // Survivor occupancy before GC - size_t _old_used_bytes_before_gc; // Old occupancy before GC - size_t _humongous_used_bytes_before_gc; // Humongous occupancy before GC - size_t _heap_used_bytes_before_gc; // Heap occupancy before GC - size_t _metaspace_used_bytes_before_gc; // Metaspace occupancy before GC - - size_t _eden_capacity_bytes_before_gc; // Eden capacity before GC - size_t _heap_capacity_bytes_before_gc; // Heap capacity before GC - // The amount of survivor regions after a collection. uint _recorded_survivor_regions; // List of survivor regions. @@ -846,6 +828,10 @@ private: public: uint tenuring_threshold() const { return _tenuring_threshold; } + uint max_survivor_regions() { + return _max_survivor_regions; + } + static const uint REGIONS_UNLIMITED = (uint) -1; uint max_regions(InCSetState dest) const { diff --git a/hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp b/hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp new file mode 100644 index 00000000000..8a74f817794 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1HeapTransition.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1HeapTransition.hpp" +#include "logging/log.hpp" +#include "memory/metaspace.hpp" + +G1HeapTransition::Data::Data(G1CollectedHeap* g1_heap) { + YoungList* young_list = g1_heap->young_list(); + _eden_length = young_list->eden_length(); + _survivor_length = young_list->survivor_length(); + _old_length = g1_heap->old_regions_count(); + _humongous_length = g1_heap->humongous_regions_count(); + _metaspace_used_bytes = MetaspaceAux::used_bytes(); +} + +G1HeapTransition::G1HeapTransition(G1CollectedHeap* g1_heap) : _g1_heap(g1_heap), _before(g1_heap) { } + +struct DetailedUsage : public StackObj { + size_t _eden_used; + size_t _survivor_used; + size_t _old_used; + size_t _humongous_used; + + size_t _eden_region_count; + size_t _survivor_region_count; + size_t _old_region_count; + size_t _humongous_region_count; + + DetailedUsage() : + _eden_used(0), _survivor_used(0), _old_used(0), _humongous_used(0), + _eden_region_count(0), _survivor_region_count(0), _old_region_count(0), _humongous_region_count(0) {} +}; + +class DetailedUsageClosure: public HeapRegionClosure { +public: + DetailedUsage _usage; + bool doHeapRegion(HeapRegion* r) { + if (r->is_old()) { + _usage._old_used += r->used(); + _usage._old_region_count++; + } else if (r->is_survivor()) { + _usage._survivor_used += r->used(); + _usage._survivor_region_count++; + } else if (r->is_eden()) { + _usage._eden_used += r->used(); + _usage._eden_region_count++; + } else if (r->is_humongous()) { + _usage._humongous_used += r->used(); + _usage._humongous_region_count++; + } else { + assert(r->used() == 0, "Expected used to be 0 but it was " SIZE_FORMAT, r->used()); + } + return false; + } +}; + +void G1HeapTransition::print() { + Data after(_g1_heap); + + size_t eden_capacity_bytes_after_gc = _g1_heap->g1_policy()->young_list_target_length() - after._survivor_length; + size_t survivor_capacity_bytes_after_gc = _g1_heap->g1_policy()->max_survivor_regions(); + + DetailedUsage usage; + if (log_is_enabled(Trace, gc, heap)) { + DetailedUsageClosure blk; + _g1_heap->heap_region_iterate(&blk); + usage = blk._usage; + assert(usage._eden_region_count == 0, "Expected no eden regions, but got " SIZE_FORMAT, usage._eden_region_count); + assert(usage._survivor_region_count == after._survivor_length, "Expected survivors to be " SIZE_FORMAT " but was " SIZE_FORMAT, + after._survivor_length, usage._survivor_region_count); + assert(usage._old_region_count == after._old_length, "Expected old to be " SIZE_FORMAT " but was " SIZE_FORMAT, + after._old_length, usage._old_region_count); + assert(usage._humongous_region_count == after._humongous_length, "Expected humongous to be " SIZE_FORMAT " but was " SIZE_FORMAT, + after._humongous_length, usage._humongous_region_count); + } + + log_info(gc, heap)("Eden regions: " SIZE_FORMAT "->" SIZE_FORMAT "(" SIZE_FORMAT ")", + _before._eden_length, after._eden_length, eden_capacity_bytes_after_gc); + log_trace(gc, heap)(" Used: 0K, Waste: 0K"); + + log_info(gc, heap)("Survivor regions: " SIZE_FORMAT "->" SIZE_FORMAT "(" SIZE_FORMAT ")", + _before._survivor_length, after._survivor_length, survivor_capacity_bytes_after_gc); + log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K", + usage._survivor_used / K, ((after._survivor_length * HeapRegion::GrainBytes) - usage._survivor_used) / K); + + log_info(gc, heap)("Old regions: " SIZE_FORMAT "->" SIZE_FORMAT, + _before._old_length, after._old_length); + log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K", + usage._old_used / K, ((after._old_length * HeapRegion::GrainBytes) - usage._old_used) / K); + + log_info(gc, heap)("Humongous regions: " SIZE_FORMAT "->" SIZE_FORMAT, + _before._humongous_length, after._humongous_length); + log_trace(gc, heap)(" Used: " SIZE_FORMAT "K, Waste: " SIZE_FORMAT "K", + usage._humongous_used / K, ((after._humongous_length * HeapRegion::GrainBytes) - usage._humongous_used) / K); + + MetaspaceAux::print_metaspace_change(_before._metaspace_used_bytes); +} diff --git a/hotspot/src/share/vm/gc/g1/g1HeapTransition.hpp b/hotspot/src/share/vm/gc/g1/g1HeapTransition.hpp new file mode 100644 index 00000000000..97db5076997 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1HeapTransition.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#ifndef SHARE_VM_GC_G1_G1HEAPTRANSITION_HPP +#define SHARE_VM_GC_G1_G1HEAPTRANSITION_HPP + +#include "gc/shared/plab.hpp" + +class G1CollectedHeap; + +class G1HeapTransition { + struct Data { + size_t _eden_length; + size_t _survivor_length; + size_t _old_length; + size_t _humongous_length; + size_t _metaspace_used_bytes; + + Data(G1CollectedHeap* g1_heap); + }; + + G1CollectedHeap* _g1_heap; + Data _before; + +public: + G1HeapTransition(G1CollectedHeap* g1_heap); + + void print(); +}; + +#endif // SHARE_VM_GC_G1_G1HEAPTRANSITION_HPP From 80e499001a07f7782cee6dcb88275d1a38b1d0b2 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Tue, 2 Feb 2016 08:27:40 -0500 Subject: [PATCH 042/139] 8135206: VM permits illegal flags for abstract methods in interfaces, versions 45.3 - 51.0 Add additional method flag checks Reviewed-by: jiangli, minqi --- hotspot/src/share/vm/classfile/classFileParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index b3a853deb3b..e3646e4980f 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -4602,8 +4602,8 @@ void ClassFileParser::verify_legal_method_modifiers(jint flags, } } else if (major_gte_15) { // Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION) - if (!is_public || is_static || is_final || is_synchronized || - is_native || !is_abstract || is_strict) { + if (!is_public || is_private || is_protected || is_static || is_final || + is_synchronized || is_native || !is_abstract || is_strict) { is_illegal = true; } } else { From 5c9133fb92ec56f46cf4530bfb077cf2e1617a73 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Tue, 2 Feb 2016 18:06:14 +0300 Subject: [PATCH 043/139] 8132721: Add tests which check that heap counters work as expected during Humongous allocations Reviewed-by: jmasa, tschatzl, dfazunen --- .../g1/humongousObjects/TestHeapCounters.java | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 hotspot/test/gc/g1/humongousObjects/TestHeapCounters.java diff --git a/hotspot/test/gc/g1/humongousObjects/TestHeapCounters.java b/hotspot/test/gc/g1/humongousObjects/TestHeapCounters.java new file mode 100644 index 00000000000..d843d35dff4 --- /dev/null +++ b/hotspot/test/gc/g1/humongousObjects/TestHeapCounters.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.humongousObjects; + +import gc.testlibrary.Helpers; +import jdk.test.lib.Asserts; +import sun.hotspot.WhiteBox; + +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @test TestHeapCounters + * @summary Checks that heap counters work as expected after humongous allocations/deallocations + * @requires vm.gc=="G1" | vm.gc=="null" + * @library /testlibrary /test/lib / + * @modules java.management + * @build sun.hotspot.WhiteBox + * gc.testlibrary.Helpers + * gc.g1.humongousObjects.TestHeapCounters + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * + * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -Xmx128m -Xms128m + * -XX:G1HeapRegionSize=1M -XX:InitiatingHeapOccupancyPercent=100 -XX:-G1UseAdaptiveIHOP + * -Xlog:gc -Xlog:gc:file=TestHeapCountersRuntime.gc.log + * gc.g1.humongousObjects.TestHeapCounters RUNTIME_COUNTER + * + * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. + * -Xmx128m -Xms128m + * -XX:G1HeapRegionSize=1M -XX:InitiatingHeapOccupancyPercent=100 -XX:-G1UseAdaptiveIHOP + * -Xlog:gc -Xlog:gc:file=TestHeapCountersMXBean.gc.log + * gc.g1.humongousObjects.TestHeapCounters MX_BEAN_COUNTER + */ +public class TestHeapCounters { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final int G1_REGION_SIZE = WHITE_BOX.g1RegionSize(); + private static final int HALF_G1_REGION_SIZE = G1_REGION_SIZE / 2; + + // Since during deallocation GC could free (very unlikely) some non-humongous data this value relaxes amount of + // memory we expect to be freed. + private static final double ALLOCATION_SIZE_TOLERANCE_FACTOR = 0.85D; + + private enum MemoryCounter { + MX_BEAN_COUNTER { + @Override + public long getUsedMemory() { + return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); + } + }, + RUNTIME_COUNTER { + @Override + public long getUsedMemory() { + return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + } + }; + + public abstract long getUsedMemory(); + } + + private static class Allocation { + private byte[] allocation; + public final long expectedSize; + + public Allocation(int allocationSize, long allocationExpectedSize) { + allocation = new byte[allocationSize]; + expectedSize = allocationExpectedSize; + + System.out.println(String.format("Object size is %d; Object is %shumongous", + WHITE_BOX.getObjectSize(allocation), + (WHITE_BOX.g1IsHumongous(allocation) ? "" : "non-"))); + + selfTest(); + } + + private void selfTest() { + boolean isHumongous = WHITE_BOX.getObjectSize(allocation) > HALF_G1_REGION_SIZE; + boolean shouldBeHumongous = WHITE_BOX.g1IsHumongous(allocation); + + // Sanity check + Asserts.assertEquals(isHumongous, shouldBeHumongous, + String.format("Test Bug: Object of size %d is expected to be %shumongous but it is not", + WHITE_BOX.getObjectSize(allocation), (shouldBeHumongous ? "" : "non-"))); + } + + public void forgetAllocation() { + allocation = null; + } + } + + public static void main(String[] args) { + + if (args.length != 1) { + throw new Error("Expected memory counter name wasn't provided as command line argument"); + } + MemoryCounter memoryCounter = MemoryCounter.valueOf(args[0].toUpperCase()); + + int byteArrayMemoryOverhead = Helpers.detectByteArrayAllocationOverhead(); + + // Largest non-humongous byte[] + int maxByteArrayNonHumongousSize = HALF_G1_REGION_SIZE - byteArrayMemoryOverhead; + + // Maximum byte[] that takes one region + int maxByteArrayOneRegionSize = G1_REGION_SIZE - byteArrayMemoryOverhead; + + List allocationSizes = Arrays.asList( + (int) maxByteArrayNonHumongousSize + 1, + (int) (0.8f * maxByteArrayOneRegionSize), + (int) (maxByteArrayOneRegionSize), + (int) (1.2f * maxByteArrayOneRegionSize), + (int) (1.5f * maxByteArrayOneRegionSize), + (int) (1.7f * maxByteArrayOneRegionSize), + (int) (2.0f * maxByteArrayOneRegionSize), + (int) (2.5f * maxByteArrayOneRegionSize) + ); + + List allocations = new ArrayList<>(); + List gcBeans = + ManagementFactory.getGarbageCollectorMXBeans(); + + long gcCountBefore = gcBeans.stream().mapToLong(GarbageCollectorMXBean::getCollectionCount).sum(); + + + System.out.println("Starting allocations - no GC should happen until we finish them"); + + for (int allocationSize : allocationSizes) { + + long usedMemoryBefore = memoryCounter.getUsedMemory(); + long expectedAllocationSize = (long) Math.ceil((double) allocationSize / G1_REGION_SIZE) * G1_REGION_SIZE; + allocations.add(new Allocation(allocationSize, expectedAllocationSize)); + long usedMemoryAfter = memoryCounter.getUsedMemory(); + + System.out.format("Expected allocation size: %d\nUsed memory before allocation: %d\n" + + "Used memory after allocation: %d\n", + expectedAllocationSize, usedMemoryBefore, usedMemoryAfter); + + long gcCountNow = gcBeans.stream().mapToLong(GarbageCollectorMXBean::getCollectionCount).sum(); + + if (gcCountNow == gcCountBefore) { + // We should allocate at least allocation.expectedSize + Asserts.assertGreaterThanOrEqual(usedMemoryAfter - usedMemoryBefore, expectedAllocationSize, + "Counter of type " + memoryCounter.getClass().getSimpleName() + + " returned wrong allocation size"); + } else { + System.out.println("GC happened during allocation so the check is skipped"); + gcCountBefore = gcCountNow; + } + } + + System.out.println("Finished allocations - no GC should have happened before this line"); + + + allocations.stream().forEach(allocation -> { + long usedMemoryBefore = memoryCounter.getUsedMemory(); + allocation.forgetAllocation(); + + WHITE_BOX.fullGC(); + + long usedMemoryAfter = memoryCounter.getUsedMemory(); + + // We should free at least allocation.expectedSize * ALLOCATION_SIZE_TOLERANCE_FACTOR + Asserts.assertGreaterThanOrEqual(usedMemoryBefore - usedMemoryAfter, + (long) (allocation.expectedSize * ALLOCATION_SIZE_TOLERANCE_FACTOR), + "Counter of type " + memoryCounter.getClass().getSimpleName() + " returned wrong allocation size"); + }); + } +} From 978ec9c9828a368753a949a5e6a2f8a9f331290b Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 2 Feb 2016 22:12:17 -0500 Subject: [PATCH 044/139] 8146616: VM exit path throws fatal error: Thread holding lock at safepoint that vm can block on: BeforeExit_lock Reviewed-by: dcubed, gthornbr --- hotspot/src/share/vm/runtime/java.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 9df11977229..84235d8803f 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -421,7 +421,10 @@ void before_exit(JavaThread* thread) { assert(_before_exit_status == BEFORE_EXIT_DONE, "invalid state"); return; case BEFORE_EXIT_DONE: - return; + // need block to avoid SS compiler bug + { + return; + } } } From ba3a7addac85954b8a4c50d4d04c0ac81e1df669 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 4 Feb 2016 08:36:38 +0100 Subject: [PATCH 045/139] 8148141: Remove fixed level padding in UL Reviewed-by: sla, mlarsson --- hotspot/src/share/vm/logging/logFileStreamOutput.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp index 757d644bf32..9c4ddf7b9c5 100644 --- a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp @@ -40,7 +40,6 @@ class LogFileStreamOutput : public LogOutput { for (size_t i = 0; i < LogDecorators::Count; i++) { _decorator_padding[i] = 0; } - _decorator_padding[LogDecorators::level_decorator] = 7; } public: From bbbbfdbf3facda4f8dd6204ede4ccf58ce1779e5 Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Wed, 3 Feb 2016 11:33:33 +0100 Subject: [PATCH 046/139] 8148944: CollectorPolicy methods for memory allocations are specific to GenCollectorPolicy Reviewed-by: jwilhelm, kbarrett --- .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 18 +-------------- .../src/share/vm/gc/g1/g1CollectorPolicy.hpp | 11 +-------- .../share/vm/gc/shared/collectorPolicy.hpp | 23 ++++--------------- .../share/vm/gc/shared/genCollectedHeap.cpp | 16 ++++++------- 4 files changed, 14 insertions(+), 54 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 815990c5628..c66db5ed191 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -736,22 +736,6 @@ void G1CollectorPolicy::update_rs_lengths_prediction(size_t prediction) { } } -HeapWord* G1CollectorPolicy::mem_allocate_work(size_t size, - bool is_tlab, - bool* gc_overhead_limit_was_exceeded) { - guarantee(false, "Not using this policy feature yet."); - return NULL; -} - -// This method controls how a collector handles one or more -// of its generations being fully allocated. -HeapWord* G1CollectorPolicy::satisfy_failed_allocation(size_t size, - bool is_tlab) { - guarantee(false, "Not using this policy feature yet."); - return NULL; -} - - #ifndef PRODUCT bool G1CollectorPolicy::verify_young_ages() { HeapRegion* head = _g1->young_list()->first_region(); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index 5df6fcdaaeb..2eca31c2175 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -621,15 +621,6 @@ public: // Create jstat counters for the policy. virtual void initialize_gc_policy_counters(); - virtual HeapWord* mem_allocate_work(size_t size, - bool is_tlab, - bool* gc_overhead_limit_was_exceeded); - - // This method controls how a collector handles one or more - // of its generations being fully allocated. - virtual HeapWord* satisfy_failed_allocation(size_t size, - bool is_tlab); - bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0); bool about_to_start_mixed_phase() const; diff --git a/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp b/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp index d42ed13b6d1..82ac817d70b 100644 --- a/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/shared/collectorPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,24 +145,9 @@ class CollectorPolicy : public CHeapObj { virtual CardTableRS* create_rem_set(MemRegion reserved); - // This method controls how a collector satisfies a request - // for a block of memory. "gc_time_limit_was_exceeded" will - // be set to true if the adaptive size policy determine that - // an excessive amount of time is being spent doing collections - // and caused a NULL to be returned. If a NULL is not returned, - // "gc_time_limit_was_exceeded" has an undefined meaning. - virtual HeapWord* mem_allocate_work(size_t size, - bool is_tlab, - bool* gc_overhead_limit_was_exceeded) = 0; - - // This method controls how a collector handles one or more - // of its generations being fully allocated. - virtual HeapWord *satisfy_failed_allocation(size_t size, bool is_tlab) = 0; - // This method controls how a collector handles a metadata allocation - // failure. - virtual MetaWord* satisfy_failed_metadata_allocation(ClassLoaderData* loader_data, - size_t size, - Metaspace::MetadataType mdtype); + MetaWord* satisfy_failed_metadata_allocation(ClassLoaderData* loader_data, + size_t size, + Metaspace::MetadataType mdtype); // Performance Counter support GCPolicyCounters* counters() { return _gc_policy_counters; } diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 6afef5c5494..2d953d6f2ad 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -289,9 +289,9 @@ HeapWord* GenCollectedHeap::attempt_allocation(size_t size, HeapWord* GenCollectedHeap::mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded) { - return collector_policy()->mem_allocate_work(size, - false /* is_tlab */, - gc_overhead_limit_was_exceeded); + return gen_policy()->mem_allocate_work(size, + false /* is_tlab */, + gc_overhead_limit_was_exceeded); } bool GenCollectedHeap::must_clear_all_soft_refs() { @@ -551,7 +551,7 @@ void GenCollectedHeap::do_collection(bool full, } HeapWord* GenCollectedHeap::satisfy_failed_allocation(size_t size, bool is_tlab) { - return collector_policy()->satisfy_failed_allocation(size, is_tlab); + return gen_policy()->satisfy_failed_allocation(size, is_tlab); } #ifdef ASSERT @@ -988,9 +988,9 @@ size_t GenCollectedHeap::unsafe_max_tlab_alloc(Thread* thr) const { HeapWord* GenCollectedHeap::allocate_new_tlab(size_t size) { bool gc_overhead_limit_was_exceeded; - return collector_policy()->mem_allocate_work(size /* size */, - true /* is_tlab */, - &gc_overhead_limit_was_exceeded); + return gen_policy()->mem_allocate_work(size /* size */, + true /* is_tlab */, + &gc_overhead_limit_was_exceeded); } // Requires "*prev_ptr" to be non-NULL. Deletes and a block of minimal size From c647cd04b07de12808afa2e6042e48549b64249e Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 3 Feb 2016 12:19:03 +0100 Subject: [PATCH 047/139] 8148945: JDK-8148481: Devirtualize Klass::vtable breaks Zero build Use Klass::method_at_vtable() instead of InstanceClass::start_of_vtable()[index] Reviewed-by: mgerdin, coleenp --- .../src/share/vm/interpreter/bytecodeInterpreter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index cab530d379c..83e6a2146f7 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -2502,10 +2502,10 @@ run: // Same comments as invokevirtual apply here. oop rcvr = STACK_OBJECT(-parms); VERIFY_OOP(rcvr); - InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass(); - callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; + Klass* rcvrKlass = rcvr->klass(); + callee = (Method*) rcvrKlass->method_at_vtable(cache->f2_as_index()); // Profile 'special case of invokeinterface' virtual call. - BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); + BI_PROFILE_UPDATE_VIRTUALCALL(rcvrKlass); } istate->set_callee(callee); istate->set_callee_entry_point(callee->from_interpreted_entry()); @@ -2594,7 +2594,7 @@ run: // but this works oop rcvr = STACK_OBJECT(-parms); VERIFY_OOP(rcvr); - InstanceKlass* rcvrKlass = (InstanceKlass*)rcvr->klass(); + Klass* rcvrKlass = rcvr->klass(); /* Executing this code in java.lang.String: public String(char value[]) { @@ -2611,9 +2611,9 @@ run: However it seems to have a vtable in the right location. Huh? Because vtables have the same offset for ArrayKlass and InstanceKlass. */ - callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()]; + callee = (Method*) rcvrKlass->method_at_vtable(cache->f2_as_index()); // Profile virtual call. - BI_PROFILE_UPDATE_VIRTUALCALL(rcvr->klass()); + BI_PROFILE_UPDATE_VIRTUALCALL(rcvrKlass); } } else { if ((Bytecodes::Code)opcode == Bytecodes::_invokespecial) { From a95454d65c1f5b482056241bb36b20587bc7497a Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Wed, 3 Feb 2016 14:15:57 +0100 Subject: [PATCH 048/139] 8148755: -XX:+HeapDumpAfterFullGC creates heap dump both before and after Full GC Reviewed-by: mgerdin, brutisso, sangheki --- hotspot/src/share/vm/gc/shared/collectedHeap.cpp | 15 ++++++++------- hotspot/src/share/vm/gc/shared/collectedHeap.hpp | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp index b4055f67e57..8feb5d819b7 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -571,10 +571,10 @@ void CollectedHeap::resize_all_tlabs() { } } -void CollectedHeap::full_gc_dump(GCTimer* timer, const char* when) { - if (HeapDumpBeforeFullGC || HeapDumpAfterFullGC) { +void CollectedHeap::full_gc_dump(GCTimer* timer, bool before) { + if ((HeapDumpBeforeFullGC && before) || (HeapDumpAfterFullGC && !before)) { GCIdMarkAndRestore gc_id_mark; - FormatBuffer<> title("Heap Dump (%s full gc)", when); + FormatBuffer<> title("Heap Dump (%s full gc)", before ? "before" : "after"); GCTraceTime(Info, gc) tm(title.buffer(), timer); HeapDumper::dump_heap(); } @@ -582,7 +582,8 @@ void CollectedHeap::full_gc_dump(GCTimer* timer, const char* when) { if (log.is_trace()) { ResourceMark rm; GCIdMarkAndRestore gc_id_mark; - FormatBuffer<> title("Class Histogram (%s full gc)", when); + FormatBuffer<> title("Class Histogram (%s full gc)", + before ? "before" : "after"); GCTraceTime(Trace, gc, classhisto) tm(title.buffer(), timer); VM_GC_HeapInspection inspector(log.trace_stream(), false /* ! full gc */); inspector.doit(); @@ -590,11 +591,11 @@ void CollectedHeap::full_gc_dump(GCTimer* timer, const char* when) { } void CollectedHeap::pre_full_gc_dump(GCTimer* timer) { - full_gc_dump(timer, "before"); + full_gc_dump(timer, true); } void CollectedHeap::post_full_gc_dump(GCTimer* timer) { - full_gc_dump(timer, "after"); + full_gc_dump(timer, false); } void CollectedHeap::initialize_reserved_region(HeapWord *start, HeapWord *end) { diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp index 7b959e994b8..613397b02d6 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -525,7 +525,7 @@ class CollectedHeap : public CHeapObj { // Generate any dumps preceding or following a full gc private: - void full_gc_dump(GCTimer* timer, const char* when); + void full_gc_dump(GCTimer* timer, bool before); public: void pre_full_gc_dump(GCTimer* timer); void post_full_gc_dump(GCTimer* timer); From 15287614fdae82f9329c9a872046962ded945b86 Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Wed, 3 Feb 2016 20:07:30 +0400 Subject: [PATCH 049/139] 8147003: Move BubbleUpRef test into CMS directory Closed test gc/4950157/BubbleUpRef.java moved to gc/cms/TestBubbleUpRef.java Reviewed-by: jwilhelm, brutisso --- hotspot/test/gc/cms/TestBubbleUpRef.java | 186 +++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 hotspot/test/gc/cms/TestBubbleUpRef.java diff --git a/hotspot/test/gc/cms/TestBubbleUpRef.java b/hotspot/test/gc/cms/TestBubbleUpRef.java new file mode 100644 index 00000000000..58fdd710ebf --- /dev/null +++ b/hotspot/test/gc/cms/TestBubbleUpRef.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.LinkedList; +import java.util.ListIterator; + +/* + * @test + * @requires vm.gc=="ConcMarkSweep" | vm.gc == "null" + * @key cte_test + * @bug 4950157 + * @summary Stress the behavior of ergonomics when the heap is nearly full and + * stays nearly full. + * @run main/othervm + * -XX:+UseConcMarkSweepGC -XX:-CMSYield -XX:-CMSPrecleanRefLists1 + * -XX:CMSInitiatingOccupancyFraction=0 -Xmx8m TestBubbleUpRef 16000 50 10000 + */ + +/** + * Test program to stress the behavior of ergonomics when the + * heap is nearly full and stays nearly full. + * This is a test to catch references that have been discovered + * during concurrent marking and whose referents have been + * cleared by the mutator. + * Allocate objects with weak references until the heap is full + * Free the objects. + * Do work so that concurrent marking has a chance to work + * Clear the referents out of the weak references + * System.gc() in the hopes that it will acquire the collection + * Free the weak references + * Do it again. + * + * Use the following VM options + * -Xmx8m -XX:-CMSYield [-XX:+UseConcMarkSweepGC] -XX:-CMSPrecleanRefLists1 + * -XX:CMSInitiatingOccupancyFraction=0 + * + * Use parameter: + * args[0] - array size (16000) + * args[1] - iterations (50) + * args[2] - work (10000) + */ +class MyList extends LinkedList { + + int[] a; + + MyList(int size) { + a = new int[size]; + } +} + +class MyRefList extends LinkedList { + + WeakReference ref; + + MyRefList(Object o, ReferenceQueue rq) { + ref = new WeakReference(o, rq); + } + + void clearReferent() { + ref.clear(); + } +} + +public class TestBubbleUpRef { + + MyList list; + MyRefList refList; + ReferenceQueue rq; + int refListLen; + int arraySize; + int iterations; + int workUnits; + + TestBubbleUpRef(int as, int cnt, int wk) { + arraySize = as; + iterations = cnt; + workUnits = wk; + list = new MyList(arraySize); + refList = new MyRefList(list, rq); + } + + public void fill() { + System.out.println("fill() " + iterations + " times"); + int count = 0; + while (true) { + try { + // Allocations + MyList next = new MyList(arraySize); + list.add(next); + MyRefList nextRef = new MyRefList(next, rq); + refList.add(nextRef); + } catch (OutOfMemoryError e) { + // When the heap is full + try { + if (count++ > iterations) { + return; + } + System.out.println("Freeing list"); + while (!list.isEmpty()) { + list.removeFirst(); + } + System.out.println("Doing work"); + int j = 0; + for (int i = 1; i < workUnits; i++) { + j = j + i; + } + System.out.println("Clearing refs"); + ListIterator listIt = refList.listIterator(); + while (listIt.hasNext()) { + MyRefList next = (MyRefList) listIt.next(); + next.clearReferent(); + } + System.gc(); + System.out.println("Freeing refs"); + while (!refList.isEmpty()) { + refList.removeFirst(); + } + } catch (OutOfMemoryError e2) { + System.err.println("Out of Memory - 2 "); + continue; + } + } catch (Exception e) { + System.err.println("Unexpected exception: " + e); + return; + } + } + } + + /** + * Test entry point. + * args[0] - array size (is the size of the int array in a list item) + * args[1] - iterations (is the number of out-of-memory exceptions before exit) + * args[2] - work (is the work done between allocations) + * @param args + */ + public static void main(String[] args) { + // Get the input parameters. + if (args.length != 3) { + throw new IllegalArgumentException("Wrong number of input argumets"); + } + + int as = Integer.parseInt(args[0]); + int cnt = Integer.parseInt(args[1]); + int work = Integer.parseInt(args[2]); + + System.out.println(" " + as + "\n" + + " " + cnt + "\n" + + " " + work + "\n"); + + // Initialization + TestBubbleUpRef b = new TestBubbleUpRef(as, cnt, work); + + // Run the test + try { + b.fill(); + } catch (OutOfMemoryError e) { + b = null; // Free memory before trying to print anything + System.err.println("Out of Memory - exiting "); + } catch (Exception e) { + System.err.println("Exiting "); + } + } +} + From 9cab990401221573e3bbdc6cbae975af33d9cca2 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Wed, 3 Feb 2016 11:40:30 -0500 Subject: [PATCH 050/139] 8079408: Reimplement TraceClassLoading, TraceClassUnloading, and TraceClassLoaderData with Unified Logging TraceClassLoading, TraceClassUnloading, and TraceClassLoaderData have been reimplemented using Unified logging. Co-authored-by: Ioi Lam Reviewed-by: iklam, coleenp, dholmes, jiangli, hseigel, rprotacio --- .../share/vm/classfile/classFileParser.cpp | 33 ++--- .../src/share/vm/classfile/classLoader.cpp | 7 +- .../share/vm/classfile/classLoaderData.cpp | 78 +++++++---- .../share/vm/classfile/classLoaderData.hpp | 1 + .../src/share/vm/classfile/javaClasses.cpp | 6 +- .../share/vm/classfile/systemDictionary.cpp | 15 +- hotspot/src/share/vm/code/nmethod.cpp | 12 +- hotspot/src/share/vm/logging/logTag.hpp | 5 +- hotspot/src/share/vm/memory/filemap.cpp | 8 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 77 ++++++++++- hotspot/src/share/vm/oops/instanceKlass.hpp | 6 +- hotspot/src/share/vm/oops/klass.cpp | 11 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 16 ++- hotspot/src/share/vm/prims/whitebox.cpp | 4 +- hotspot/src/share/vm/runtime/arguments.cpp | 18 ++- hotspot/src/share/vm/runtime/globals.hpp | 9 -- .../share/vm/services/classLoadingService.cpp | 24 ++-- .../share/vm/services/classLoadingService.hpp | 5 +- .../jsr292/CallSiteDepContextTest.java | 4 +- .../runtime/logging/ClassLoadUnloadTest.java | 128 ++++++++++++++++++ .../runtime/logging/classes/test/Empty.java | 5 + .../testlibrary/ClassUnloadCommon.java | 8 +- 22 files changed, 358 insertions(+), 122 deletions(-) create mode 100644 hotspot/test/runtime/logging/ClassLoadUnloadTest.java create mode 100644 hotspot/test/runtime/logging/classes/test/Empty.java diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index e3646e4980f..0d693c3890d 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "classfile/verifier.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/gcLocker.hpp" +#include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" @@ -5347,30 +5348,12 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) { ClassLoadingService::notify_class_loaded(ik, false /* not shared class */); if (!is_internal()) { - if (TraceClassLoading) { - ResourceMark rm; - // print in a single call to reduce interleaving of output - if (_stream->source() != NULL) { - tty->print("[Loaded %s from %s]\n", - ik->external_name(), - _stream->source()); - } else if (_loader_data->class_loader() == NULL) { - const Klass* const caller = - THREAD->is_Java_thread() - ? ((JavaThread*)THREAD)->security_get_caller_class(1) - : NULL; - // caller can be NULL, for example, during a JVMTI VM_Init hook - if (caller != NULL) { - tty->print("[Loaded %s by instance of %s]\n", - ik->external_name(), - caller->external_name()); - } else { - tty->print("[Loaded %s]\n", ik->external_name()); - } - } else { - tty->print("[Loaded %s from %s]\n", ik->external_name(), - _loader_data->class_loader()->klass()->external_name()); - } + if (log_is_enabled(Info, classload)) { + ik->print_loading_log(LogLevel::Info, _loader_data, _stream); + } + // No 'else' here as logging levels are not mutually exclusive + if (log_is_enabled(Debug, classload)) { + ik->print_loading_log(LogLevel::Debug, _loader_data, _stream); } if (log_is_enabled(Info, classresolve)) { diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 3881be599a7..14feb9876cf 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -578,15 +578,14 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str } } } - if (TraceClassLoading || TraceClassPaths) { + if (TraceClassPaths) { tty->print_cr("[Opened %s]", path); } + log_info(classload)("opened: %s", path); } else { // Directory new_entry = new ClassPathDirEntry(path); - if (TraceClassLoading) { - tty->print_cr("[Path %s]", path); - } + log_info(classload)("path: %s", path); } return new_entry; } diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 31de9b4836f..9543a1fac7b 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,12 +54,14 @@ #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "gc/shared/gcLocker.hpp" +#include "logging/log.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.inline.hpp" +#include "runtime/javaCalls.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" #include "runtime/safepoint.hpp" @@ -286,9 +288,9 @@ void ClassLoaderData::add_class(Klass* k, bool publicize /* true */) { _klasses = k; } - if (publicize && TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) { + if (publicize && k->class_loader_data() != NULL) { ResourceMark rm; - tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: " + log_trace(classloaderdata)("Adding k: " PTR_FORMAT " %s to CLD: " PTR_FORMAT " loader: " PTR_FORMAT " %s", p2i(k), k->external_name(), @@ -326,15 +328,16 @@ void ClassLoaderData::unload() { // Tell serviceability tools these classes are unloading classes_do(InstanceKlass::notify_unload_class); - if (TraceClassLoaderData) { + if (log_is_enabled(Debug, classloaderdata)) { ResourceMark rm; - tty->print("[ClassLoaderData: unload loader data " INTPTR_FORMAT, p2i(this)); - tty->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()), + outputStream* log = LogHandle(classloaderdata)::debug_stream(); + log->print(": unload loader data " INTPTR_FORMAT, p2i(this)); + log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()), loader_name()); if (is_anonymous()) { - tty->print(" for anonymous class " INTPTR_FORMAT " ", p2i(_klasses)); + log->print(" for anonymous class " INTPTR_FORMAT " ", p2i(_klasses)); } - tty->print_cr("]"); + log->cr(); } } @@ -408,13 +411,13 @@ Metaspace* ClassLoaderData::metaspace_non_null() { assert (class_loader() == NULL, "Must be"); set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType)); } else if (is_anonymous()) { - if (TraceClassLoaderData && Verbose && class_loader() != NULL) { - tty->print_cr("is_anonymous: %s", class_loader()->klass()->internal_name()); + if (class_loader() != NULL) { + log_trace(classloaderdata)("is_anonymous: %s", class_loader()->klass()->internal_name()); } set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType)); } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { - if (TraceClassLoaderData && Verbose && class_loader() != NULL) { - tty->print_cr("is_reflection: %s", class_loader()->klass()->internal_name()); + if (class_loader() != NULL) { + log_trace(classloaderdata)("is_reflection: %s", class_loader()->klass()->internal_name()); } set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType)); } else { @@ -601,21 +604,47 @@ ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous, TRA cld->set_next(next); ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next); if (exchanged == next) { - if (TraceClassLoaderData) { - ResourceMark rm; - tty->print("[ClassLoaderData: "); - tty->print("create class loader data " INTPTR_FORMAT, p2i(cld)); - tty->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()), - cld->loader_name()); - tty->print_cr("]"); + if (log_is_enabled(Debug, classloaderdata)) { + PauseNoSafepointVerifier pnsv(&no_safepoints); // Need safe points for JavaCalls::call_virtual + log_creation(loader, cld, CHECK_NULL); } return cld; } next = exchanged; } while (true); - } +void ClassLoaderDataGraph::log_creation(Handle loader, ClassLoaderData* cld, TRAPS) { + Handle string; + if (loader.not_null()) { + // Include the result of loader.toString() in the output. This allows + // the user of the log to identify the class loader instance. + JavaValue result(T_OBJECT); + KlassHandle spec_klass(THREAD, SystemDictionary::ClassLoader_klass()); + JavaCalls::call_virtual(&result, + loader, + spec_klass, + vmSymbols::toString_name(), + vmSymbols::void_string_signature(), + CHECK); + assert(result.get_type() == T_OBJECT, "just checking"); + string = (oop)result.get_jobject(); + } + + ResourceMark rm; + outputStream* log = LogHandle(classloaderdata)::debug_stream(); + log->print("create class loader data " INTPTR_FORMAT, p2i(cld)); + log->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()), + cld->loader_name()); + + if (string.not_null()) { + log->print(": "); + java_lang_String::print(string(), log); + } + log->cr(); +} + + void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) { cld->oops_do(f, klass_closure, must_claim); @@ -709,10 +738,11 @@ GrowableArray* ClassLoaderDataGraph::new_clds() { if (!curr->claimed()) { array->push(curr); - if (TraceClassLoaderData) { - tty->print("[ClassLoaderData] found new CLD: "); - curr->print_value_on(tty); - tty->cr(); + if (log_is_enabled(Debug, classloaderdata)) { + outputStream* log = LogHandle(classloaderdata)::debug_stream(); + log->print("found new CLD: "); + curr->print_value_on(log); + log->cr(); } } diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index d208fde85fb..f6e82fa12bc 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -116,6 +116,7 @@ class ClassLoaderDataGraph : public AllStatic { static void dump_on(outputStream * const out) PRODUCT_RETURN; static void dump() { dump_on(tty); } static void verify(); + static void log_creation(Handle loader, ClassLoaderData* cld, TRAPS); static bool unload_list_contains(const void* x); #ifndef PRODUCT diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 90f9df5451f..60834c3855d 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,7 +129,7 @@ compute_offset(int &dest_offset, tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT - vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:classload=info to see the origin of the problem class"); } dest_offset = fd.offset(); } @@ -3958,7 +3958,7 @@ int InjectedField::compute_offset() { tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT - vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:classload=info to see the origin of the problem class"); return -1; } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 1519118932a..2e7ab518471 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1302,14 +1302,13 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh)); } - if (TraceClassLoading) { - ResourceMark rm; - tty->print("[Loaded %s", ik->external_name()); - tty->print(" from shared objects file"); - if (class_loader.not_null()) { - tty->print(" by %s", loader_data->loader_name()); - } - tty->print_cr("]"); + if (log_is_enabled(Info, classload)) { + ik()->print_loading_log(LogLevel::Info, loader_data, NULL); + } + // No 'else' here as logging levels are not mutually exclusive + + if (log_is_enabled(Debug, classload)) { + ik()->print_loading_log(LogLevel::Debug, loader_data, NULL); } if (DumpLoadedClassList != NULL && classlist_file->is_open()) { diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 9a59b7258da..544a55663f1 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" +#include "logging/log.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" #endif @@ -1310,13 +1311,14 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) { flush_dependencies(is_alive); // Break cycle between nmethod & method - if (TraceClassUnloading && WizardMode) { - tty->print_cr("[Class unloading: Making nmethod " INTPTR_FORMAT - " unloadable], Method*(" INTPTR_FORMAT + if (log_is_enabled(Trace, classunload)) { + outputStream* log = LogHandle(classunload)::trace_stream(); + log->print_cr("making nmethod " INTPTR_FORMAT + " unloadable, Method*(" INTPTR_FORMAT "), cause(" INTPTR_FORMAT ")", p2i(this), p2i(_method), p2i(cause)); if (!Universe::heap()->is_gc_active()) - cause->klass()->print(); + cause->klass()->print_on(log); } // Unlink the osr method, so we do not look this up again if (is_osr_method()) { diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 9f166118219..5777c7a8b99 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,9 @@ LOG_TAG(classhisto) \ LOG_TAG(classresolve) \ LOG_TAG(classinit) \ + LOG_TAG(classload) /* Trace all classes loaded */ \ + LOG_TAG(classloaderdata) /* class loader loader_data lifetime */ \ + LOG_TAG(classunload) /* Trace unloading of classes */ \ LOG_TAG(comp) \ LOG_TAG(compaction) \ LOG_TAG(cpu) \ diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 59c82277c07..2a82e60c063 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,7 +208,7 @@ void FileMapInfo::allocate_classpath_entry_table() { count ++; bytes += (int)entry_size; bytes += name_bytes; - if (TraceClassPaths || (TraceClassLoading && Verbose)) { + if (TraceClassPaths) { tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); } } else { @@ -275,7 +275,7 @@ bool FileMapInfo::validate_classpath_entry_table() { struct stat st; const char* name = ent->_name; bool ok = true; - if (TraceClassPaths || (TraceClassLoading && Verbose)) { + if (TraceClassPaths) { tty->print_cr("[Checking shared classpath entry: %s]", name); } if (os::stat(name, &st) != 0) { @@ -301,7 +301,7 @@ bool FileMapInfo::validate_classpath_entry_table() { } } if (ok) { - if (TraceClassPaths || (TraceClassLoading && Verbose)) { + if (TraceClassPaths) { tty->print_cr("[ok]"); } } else if (!PrintSharedArchiveAndExit) { diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 1638f9dd508..0ae310bdaf6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classFileParser.hpp" +#include "classfile/classFileStream.hpp" #include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/verifier.hpp" @@ -35,6 +36,7 @@ #include "interpreter/oopMapCache.hpp" #include "interpreter/rewriter.hpp" #include "jvmtifiles/jvmti.h" +#include "logging/log.hpp" #include "memory/heapInspection.hpp" #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" @@ -2904,6 +2906,79 @@ const char* InstanceKlass::internal_name() const { return external_name(); } +void InstanceKlass::print_loading_log(LogLevel::type type, + ClassLoaderData* loader_data, + const ClassFileStream* cfs) const { + ResourceMark rm; + outputStream* log; + + assert(type == LogLevel::Info || type == LogLevel::Debug, "sanity"); + + if (type == LogLevel::Info) { + log = LogHandle(classload)::info_stream(); + } else { + assert(type == LogLevel::Debug, + "print_loading_log supports only Debug and Info levels"); + log = LogHandle(classload)::debug_stream(); + } + + // Name and class hierarchy info + log->print("%s", external_name()); + + // Source + if (cfs != NULL) { + if (cfs->source() != NULL) { + log->print(" source: %s", cfs->source()); + } else if (loader_data == ClassLoaderData::the_null_class_loader_data()) { + Thread* THREAD = Thread::current(); + Klass* caller = + THREAD->is_Java_thread() + ? ((JavaThread*)THREAD)->security_get_caller_class(1) + : NULL; + // caller can be NULL, for example, during a JVMTI VM_Init hook + if (caller != NULL) { + log->print(" source: instance of %s", caller->external_name()); + } else { + // source is unknown + } + } else { + Handle class_loader(loader_data->class_loader()); + log->print(" source: %s", class_loader->klass()->external_name()); + } + } else { + log->print(" source: shared objects file"); + } + + if (type == LogLevel::Debug) { + // Class hierarchy info + log->print(" klass: " INTPTR_FORMAT " super: " INTPTR_FORMAT, + p2i(this), p2i(superklass())); + + if (local_interfaces() != NULL && local_interfaces()->length() > 0) { + log->print(" interfaces:"); + int length = local_interfaces()->length(); + for (int i = 0; i < length; i++) { + log->print(" " INTPTR_FORMAT, + p2i(InstanceKlass::cast(local_interfaces()->at(i)))); + } + } + + // Class loader + log->print(" loader: ["); + loader_data->print_value_on(log); + log->print("]"); + + // Classfile checksum + if (cfs) { + log->print(" bytes: %d checksum: %08x", + cfs->length(), + ClassLoader::crc32(0, (const char*)cfs->buffer(), + cfs->length())); + } + } + log->cr(); +} + #if INCLUDE_SERVICES // Size Statistics void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 5c79ba530d9..f7a3a24800f 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "classfile/classLoaderData.hpp" #include "gc/shared/specialized_oop_closures.hpp" +#include "logging/logLevel.hpp" #include "memory/referenceType.hpp" #include "oops/annotations.hpp" #include "oops/constMethod.hpp" @@ -1244,6 +1245,9 @@ public: void verify_on(outputStream* st); void oop_verify_on(oop obj, outputStream* st); + + // Logging + void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, const ClassFileStream* cfs) const; }; // for adding methods diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 46d62102563..ac237fa0f43 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/collectedHeap.inline.hpp" +#include "logging/log.hpp" #include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" @@ -386,9 +387,9 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive Klass* sub = current->subklass(); while (sub != NULL && !sub->is_loader_alive(is_alive)) { #ifndef PRODUCT - if (TraceClassUnloading && WizardMode) { + if (log_is_enabled(Trace, classunload)) { ResourceMark rm; - tty->print_cr("[Unlinking class (subclass) %s]", sub->external_name()); + log_trace(classunload)("unlinking class (subclass): %s", sub->external_name()); } #endif sub = sub->next_sibling(); @@ -401,9 +402,9 @@ void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive // Find and set the first alive sibling Klass* sibling = current->next_sibling(); while (sibling != NULL && !sibling->is_loader_alive(is_alive)) { - if (TraceClassUnloading && WizardMode) { + if (log_is_enabled(Trace, classunload)) { ResourceMark rm; - tty->print_cr("[Unlinking class (sibling) %s]", sibling->external_name()); + log_trace(classunload)("[Unlinking class (sibling) %s]", sibling->external_name()); } sibling = sibling->next_sibling(); } diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index a699b79ed95..c2b5289a21d 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "jvmtifiles/jvmtiEnv.hpp" +#include "logging/log.hpp" #include "logging/logConfiguration.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" @@ -473,9 +474,7 @@ JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) { ObjectLocker ol(loader_lock, thread); // add the jar file to the bootclasspath - if (TraceClassLoading) { - tty->print_cr("[Opened %s]", zip_entry->name()); - } + log_info(classload)("opened: %s", zip_entry->name()); ClassLoaderExt::append_boot_classpath(zip_entry); return JVMTI_ERROR_NONE; } else { @@ -625,8 +624,13 @@ JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) { // ignore break; case JVMTI_VERBOSE_CLASS: - TraceClassLoading = value != 0; - TraceClassUnloading = value != 0; + if (value == 0) { + LogConfiguration::parse_log_arguments("stdout", "classunload=off", NULL, NULL, NULL); + LogConfiguration::parse_log_arguments("stdout", "classload=off", NULL, NULL, NULL); + } else { + LogConfiguration::parse_log_arguments("stdout", "classload=info", NULL, NULL, NULL); + LogConfiguration::parse_log_arguments("stdout", "classunload=info", NULL, NULL, NULL); + } break; case JVMTI_VERBOSE_GC: if (value == 0) { diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 39e8a4bde15..202d419ab46 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1407,7 +1407,7 @@ int WhiteBox::offset_for_field(const char* field_name, oop object, if (res == NULL) { tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); - vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:classload=info to see the origin of the problem class"); } //fetch the field at the offset we've found diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5134ab58ff8..2d41950f305 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -402,10 +402,12 @@ static AliasedFlag const aliased_jvm_flags[] = { }; static AliasedLoggingFlag const aliased_logging_flags[] = { - { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, - { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions }, - { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation }, - { NULL, LogLevel::Off, false, LogTag::__NO_TAG } + { "TraceClassLoading", LogLevel::Info, true, LogTag::_classload }, + { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload }, + { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, + { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions }, + { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation }, + { NULL, LogLevel::Off, false, LogTag::__NO_TAG } }; // Return true if "v" is less than "other", where "other" may be "undefined". @@ -2653,12 +2655,8 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // -verbose:[class/gc/jni] if (match_option(option, "-verbose", &tail)) { if (!strcmp(tail, ":class") || !strcmp(tail, "")) { - if (FLAG_SET_CMDLINE(bool, TraceClassLoading, true) != Flag::SUCCESS) { - return JNI_EINVAL; - } - if (FLAG_SET_CMDLINE(bool, TraceClassUnloading, true) != Flag::SUCCESS) { - return JNI_EINVAL; - } + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classload)); + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classunload)); } else if (!strcmp(tail, ":gc")) { LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(gc)); } else if (!strcmp(tail, ":jni")) { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 5cfbf11f45d..62f177a7400 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2416,21 +2416,12 @@ public: product(bool, TraceClassPaths, false, \ "Trace processing of class paths") \ \ - product_rw(bool, TraceClassLoading, false, \ - "Trace all classes loaded") \ - \ product(bool, TraceClassLoadingPreorder, false, \ "Trace all classes loaded in order referenced (not loaded)") \ \ - product_rw(bool, TraceClassUnloading, false, \ - "Trace unloading of classes") \ - \ product_rw(bool, TraceLoaderConstraints, false, \ "Trace loader constraints") \ \ - develop(bool, TraceClassLoaderData, false, \ - "Trace class loader loader_data lifetime") \ - \ product(size_t, InitialBootClassLoaderMetaspaceSize, \ NOT_LP64(2200*K) LP64_ONLY(4*M), \ "Initial size of the boot class loader data metaspace") \ diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 24c76e5d172..4acb22502ce 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 +33,8 @@ #include "utilities/dtrace.hpp" #include "utilities/macros.hpp" #include "utilities/defaultStream.hpp" +#include "logging/log.hpp" +#include "logging/logConfiguration.hpp" #ifdef DTRACE_ENABLED @@ -135,9 +137,9 @@ void ClassLoadingService::notify_class_unloaded(InstanceKlass* k) { } } - if (TraceClassUnloading) { + if (log_is_enabled(Info, classunload)) { ResourceMark rm; - tty->print_cr("[Unloading class %s " INTPTR_FORMAT "]", k->external_name(), p2i(k)); + log_info(classunload)("unloading class %s " INTPTR_FORMAT , k->external_name(), p2i(k)); } } @@ -179,12 +181,13 @@ size_t ClassLoadingService::compute_class_size(InstanceKlass* k) { bool ClassLoadingService::set_verbose(bool verbose) { MutexLocker m(Management_lock); - // verbose will be set to the previous value - Flag::Error error = CommandLineFlags::boolAtPut("TraceClassLoading", &verbose, Flag::MANAGEMENT); - assert(error==Flag::SUCCESS, "Setting TraceClassLoading flag failed with error %s", Flag::flag_error_str(error)); + if (verbose) { + LogConfiguration::parse_log_arguments("stdout", "classload=info", NULL, NULL, NULL); + } else { + LogConfiguration::parse_log_arguments("stdout", "classload=off", NULL, NULL, NULL); + } reset_trace_class_unloading(); - return verbose; } @@ -192,8 +195,11 @@ bool ClassLoadingService::set_verbose(bool verbose) { void ClassLoadingService::reset_trace_class_unloading() { assert(Management_lock->owned_by_self(), "Must own the Management_lock"); bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose(); - Flag::Error error = CommandLineFlags::boolAtPut("TraceClassUnloading", &value, Flag::MANAGEMENT); - assert(error==Flag::SUCCESS, "Setting TraceClassUnLoading flag failed with error %s", Flag::flag_error_str(error)); + if (value) { + LogConfiguration::parse_log_arguments("stdout", "classunload=info", NULL, NULL, NULL); + } else { + LogConfiguration::parse_log_arguments("stdout", "classunload=off", NULL, NULL, NULL); + } } GrowableArray* LoadedClassesEnumerator::_loaded_classes = NULL; diff --git a/hotspot/src/share/vm/services/classLoadingService.hpp b/hotspot/src/share/vm/services/classLoadingService.hpp index 9d85c92d5f7..16ff40fd4be 100644 --- a/hotspot/src/share/vm/services/classLoadingService.hpp +++ b/hotspot/src/share/vm/services/classLoadingService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_VM_SERVICES_CLASSLOADINGSERVICE_HPP #define SHARE_VM_SERVICES_CLASSLOADINGSERVICE_HPP +#include "logging/log.hpp" #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "utilities/growableArray.hpp" @@ -54,7 +55,7 @@ private: public: static void init(); - static bool get_verbose() { return TraceClassLoading; } + static bool get_verbose() { return log_is_enabled(Info, classload); } static bool set_verbose(bool verbose); static void reset_trace_class_unloading() NOT_MANAGEMENT_RETURN; diff --git a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java index d65bf424228..e650aa558c1 100644 --- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java +++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /** * @test * @bug 8057967 - * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading + * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -Xlog:classunload * -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC * -verbose:gc java.lang.invoke.CallSiteDepContextTest */ diff --git a/hotspot/test/runtime/logging/ClassLoadUnloadTest.java b/hotspot/test/runtime/logging/ClassLoadUnloadTest.java new file mode 100644 index 00000000000..85cf5cb2284 --- /dev/null +++ b/hotspot/test/runtime/logging/ClassLoadUnloadTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 ClassLoadUnloadTest + * @bug 8142506 + * @library /testlibrary /runtime/testlibrary + * @library classes + * @build ClassUnloadCommon test.Empty jdk.test.lib.* jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver ClassLoadUnloadTest + */ + +import jdk.test.lib.*; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ClassLoadUnloadTest { + private static OutputAnalyzer out; + private static ProcessBuilder pb; + private static class ClassUnloadTestMain { + public static void main(String... args) throws Exception { + String className = "test.Empty"; + ClassLoader cl = ClassUnloadCommon.newClassLoader(); + Class c = cl.loadClass(className); + cl = null; c = null; + ClassUnloadCommon.triggerUnloading(); + } + } + + static void checkFor(String... outputStrings) throws Exception { + out = new OutputAnalyzer(pb.start()); + for (String s: outputStrings) { + out.shouldContain(s); + } + out.shouldHaveExitValue(0); + } + + static void checkAbsent(String... outputStrings) throws Exception { + out = new OutputAnalyzer(pb.start()); + for (String s: outputStrings) { + out.shouldNotContain(s); + } + out.shouldHaveExitValue(0); + } + + // Use the same command-line heap size setting as ../ClassUnload/UnloadTest.java + static ProcessBuilder exec(String... args) throws Exception { + List argsList = new ArrayList<>(); + Collections.addAll(argsList, args); + Collections.addAll(argsList, "-Xmn8m"); + Collections.addAll(argsList, "-Dtest.classes=" + System.getProperty("test.classes",".")); + Collections.addAll(argsList, ClassUnloadTestMain.class.getName()); + return ProcessTools.createJavaProcessBuilder(argsList.toArray(new String[argsList.size()])); + } + + public static void main(String... args) throws Exception { + + // -Xlog:classunload=info + pb = exec("-Xlog:classunload=info"); + checkFor("[classunload]", "unloading class"); + + // -Xlog:classunload=off + pb = exec("-Xlog:classunload=off"); + checkAbsent("[classunload]"); + + // -XX:+TraceClassUnloading + pb = exec("-XX:+TraceClassUnloading"); + checkFor("[classunload]", "unloading class"); + + // -XX:-TraceClassUnloading + pb = exec("-XX:-TraceClassUnloading"); + checkAbsent("[classunload]"); + + // -Xlog:classload=info + pb = exec("-Xlog:classload=info"); + checkFor("[classload]", "java.lang.Object", "source:"); + + // -Xlog:classload=debug + pb = exec("-Xlog:classload=debug"); + checkFor("[classload]", "java.lang.Object", "source:", "klass:", "super:", "loader:", "bytes:"); + + // -Xlog:classload=off + pb = exec("-Xlog:classload=off"); + checkAbsent("[classload]"); + + // -XX:+TraceClassLoading + pb = exec("-XX:+TraceClassLoading"); + checkFor("[classload]", "java.lang.Object", "source:"); + + // -XX:-TraceClassLoading + pb = exec("-XX:-TraceClassLoading"); + checkAbsent("[classload]"); + + // -verbose:class + pb = exec("-verbose:class"); + checkFor("[classload]", "java.lang.Object", "source:"); + checkFor("[classunload]", "unloading class"); + + // -Xlog:classloaderdata=trace + pb = exec("-Xlog:classloaderdata=trace"); + checkFor("[classloaderdata]", "create class loader data"); + + } +} diff --git a/hotspot/test/runtime/logging/classes/test/Empty.java b/hotspot/test/runtime/logging/classes/test/Empty.java new file mode 100644 index 00000000000..cf3e5f5199d --- /dev/null +++ b/hotspot/test/runtime/logging/classes/test/Empty.java @@ -0,0 +1,5 @@ +package test; + +public class Empty { +public String toString() { return "nothing"; } +} diff --git a/hotspot/test/runtime/testlibrary/ClassUnloadCommon.java b/hotspot/test/runtime/testlibrary/ClassUnloadCommon.java index 06729ac6a86..d92361396bb 100644 --- a/hotspot/test/runtime/testlibrary/ClassUnloadCommon.java +++ b/hotspot/test/runtime/testlibrary/ClassUnloadCommon.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,12 @@ * questions. */ + +/* + * To use ClassUnloadCommon from a sub-process, see hotspot/test/runtime/logging/ClassLoadUnloadTest.java + * for an example. + */ + import java.io.File; import java.net.MalformedURLException; import java.net.URL; From d98409eadb7e27f5c7e9a9872d0d5506f9794e0a Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 3 Feb 2016 17:26:36 +0000 Subject: [PATCH 051/139] 8146984: SIGBUS: bool Method::has_method_vptr(const void*)+0xc Add address check and use SafeFetchN for Method* vptr access when Method* may be bad pointer. Reviewed-by: dcubed, mgronlun --- hotspot/src/share/vm/oops/method.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index eebf233a555..2d06a42c10d 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -55,6 +55,7 @@ #include "runtime/relocator.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" +#include "runtime/stubRoutines.hpp" #include "utilities/quickSort.hpp" #include "utilities/xmlstream.hpp" @@ -2098,23 +2099,29 @@ void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { } bool Method::has_method_vptr(const void* ptr) { - Method m; + // Use SafeFetch to check if this is a valid pointer first // This assumes that the vtbl pointer is the first word of a C++ object. - // This assumption is also in universe.cpp patch_klass_vtble - void* vtbl2 = dereference_vptr((const void*)&m); - void* this_vtbl = dereference_vptr(ptr); - return vtbl2 == this_vtbl; + // This assumption is also in universe.cpp patch_klass_vtable + intptr_t this_vptr = SafeFetchN((intptr_t*)ptr, intptr_t(1)); + if (this_vptr == 1) { + return false; + } + Method m; + return (intptr_t)dereference_vptr(&m) == this_vptr; } // Check that this pointer is valid by checking that the vtbl pointer matches bool Method::is_valid_method() const { if (this == NULL) { return false; - } else if (!is_metaspace_object()) { - return false; - } else { - return has_method_vptr((const void*)this); } + + // Quick sanity check on pointer. + if ((intptr_t(this) & (wordSize-1)) != 0) { + return false; + } + + return has_method_vptr(this); } #ifndef PRODUCT From 61a27307a476124a614d6fb0cacc4b27cf74c1c1 Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Wed, 3 Feb 2016 09:31:22 -0800 Subject: [PATCH 052/139] 8147884: Names of GC threads should be set before the threads start Reviewed-by: mgerdin, david --- hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index aabf6790d80..dc1b5ea1352 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,10 +59,10 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex _monitor = DirtyCardQ_CBL_mon; } initialize(); - create_and_start(); // set name set_name("G1 Refine#%d", worker_id); + create_and_start(); } void ConcurrentG1RefineThread::initialize() { diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp index cc0506da12a..b511b04617f 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,9 +61,8 @@ G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread( true, Monitor::_safepoint_check_never); - create_and_start(); - set_name("G1 Young RemSet Sampling"); + create_and_start(); } void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { From 2cabd2fca3ec8045b462cc412aad7248fc83faee Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Wed, 3 Feb 2016 13:42:29 -0800 Subject: [PATCH 053/139] 8148747: [TESTBUG] runtime/Unsafe/AllocateMemory.java fails with OOM during compilation Reviewed-by: coleenp, gtriantafill --- hotspot/test/runtime/Unsafe/AllocateMemory.java | 3 ++- hotspot/test/runtime/Unsafe/Reallocate.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/test/runtime/Unsafe/AllocateMemory.java b/hotspot/test/runtime/Unsafe/AllocateMemory.java index a86c463137b..0bc26727b51 100644 --- a/hotspot/test/runtime/Unsafe/AllocateMemory.java +++ b/hotspot/test/runtime/Unsafe/AllocateMemory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @requires vm.compMode != "Xcomp" * @summary Verifies behaviour of Unsafe.allocateMemory * @library /testlibrary * @modules java.base/sun.misc diff --git a/hotspot/test/runtime/Unsafe/Reallocate.java b/hotspot/test/runtime/Unsafe/Reallocate.java index 606845f2e42..4f441586486 100644 --- a/hotspot/test/runtime/Unsafe/Reallocate.java +++ b/hotspot/test/runtime/Unsafe/Reallocate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @requires vm.compMode != "Xcomp" * @bug 8058897 * @library /testlibrary * @modules java.base/sun.misc From 5f51924702cc7138f3e6bd1ae616b765b85a3b45 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Wed, 3 Feb 2016 18:18:00 +0100 Subject: [PATCH 054/139] 8148960: Humongous mis-spelled in log output Reviewed-by: huntch, jwilhelm --- hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp | 8 ++++---- hotspot/test/gc/g1/TestRemsetLoggingTools.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp b/hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp index 8cd76fd9ffc..5b226d1d5a4 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp @@ -221,7 +221,7 @@ public: class HRRSStatsIter: public HeapRegionClosure { private: RegionTypeCounter _young; - RegionTypeCounter _humonguous; + RegionTypeCounter _humongous; RegionTypeCounter _free; RegionTypeCounter _old; RegionTypeCounter _all; @@ -245,7 +245,7 @@ private: HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; } public: - HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"), + HRRSStatsIter() : _all("All"), _young("Young"), _humongous("Humongous"), _free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL), _max_rs_mem_sz(0), _max_code_root_mem_sz(0) {} @@ -274,7 +274,7 @@ public: } else if (r->is_young()) { current = &_young; } else if (r->is_humongous()) { - current = &_humonguous; + current = &_humongous; } else if (r->is_old()) { current = &_old; } else { @@ -287,7 +287,7 @@ public: } void print_summary_on(outputStream* out) { - RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL }; + RegionTypeCounter* counters[] = { &_young, &_humongous, &_free, &_old, NULL }; out->print_cr(" Current rem set statistics"); out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "K." diff --git a/hotspot/test/gc/g1/TestRemsetLoggingTools.java b/hotspot/test/gc/g1/TestRemsetLoggingTools.java index 905d572ba15..e58eb9e8b14 100644 --- a/hotspot/test/gc/g1/TestRemsetLoggingTools.java +++ b/hotspot/test/gc/g1/TestRemsetLoggingTools.java @@ -96,7 +96,7 @@ public class TestRemsetLoggingTools { public static void expectPerRegionRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception { expectRSetSummaries(result, expectedCumulative, expectedPeriodic); int actualYoung = result.split("Young regions").length - 1; - int actualHumonguous = result.split("Humonguous regions").length - 1; + int actualHumongous = result.split("Humongous regions").length - 1; int actualFree = result.split("Free regions").length - 1; int actualOther = result.split("Old regions").length - 1; @@ -104,7 +104,7 @@ public class TestRemsetLoggingTools { int expectedPerRegionTypeInfo = (expectedCumulative + expectedPeriodic) * 4; checkCounts(expectedPerRegionTypeInfo, actualYoung, "Young"); - checkCounts(expectedPerRegionTypeInfo, actualHumonguous, "Humonguous"); + checkCounts(expectedPerRegionTypeInfo, actualHumongous, "Humongous"); checkCounts(expectedPerRegionTypeInfo, actualFree, "Free"); checkCounts(expectedPerRegionTypeInfo, actualOther, "Old"); } From 433bc5e2bc2cf752f529665993b1ee79d7a8ef05 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Wed, 3 Feb 2016 18:21:43 +0100 Subject: [PATCH 055/139] 8148951: Remove unused method Generation::performs_in_place_marking() Reviewed-by: david, jwilhelm --- hotspot/src/share/vm/gc/serial/defNewGeneration.hpp | 3 --- hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp | 3 --- hotspot/src/share/vm/gc/shared/generation.hpp | 7 ------- 3 files changed, 13 deletions(-) diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp index f42c8ed8b47..484a6b6aa52 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp @@ -285,9 +285,6 @@ protected: // Save the tops for eden, from, and to virtual void record_spaces_top(); - // Doesn't require additional work during GC prologue and epilogue - virtual bool performs_in_place_marking() const { return false; } - // Accessing marks void save_marks(); void reset_saved_marks(); diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 6afef5c5494..9ccd2a6c44c 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -458,7 +458,6 @@ void GenCollectedHeap::do_collection(bool full, prepared_for_verification = true; } - assert(!_young_gen->performs_in_place_marking(), "No young generation do in place marking"); collect_generation(_young_gen, full, size, @@ -489,8 +488,6 @@ void GenCollectedHeap::do_collection(bool full, prepare_for_verify(); } - assert(_old_gen->performs_in_place_marking(), "All old generations do in place marking"); - if (do_young_collection) { // We did a young GC. Need a new GC id for the old GC. GCIdMarkAndRestore gc_id_mark; diff --git a/hotspot/src/share/vm/gc/shared/generation.hpp b/hotspot/src/share/vm/gc/shared/generation.hpp index 9e1eed7d9f4..6b60291d129 100644 --- a/hotspot/src/share/vm/gc/shared/generation.hpp +++ b/hotspot/src/share/vm/gc/shared/generation.hpp @@ -309,13 +309,6 @@ class Generation: public CHeapObj { // do nothing. virtual void par_oop_since_save_marks_iterate_done(int thread_num) {} - // This generation does in-place marking, meaning that mark words - // are mutated during the marking phase and presumably reinitialized - // to a canonical value after the GC. This is currently used by the - // biased locking implementation to determine whether additional - // work is required during the GC prologue and epilogue. - virtual bool performs_in_place_marking() const { return true; } - // Returns "true" iff collect() should subsequently be called on this // this generation. See comment below. // This is a generic implementation which can be overridden. From 00aa34d7881943cab087d09cfb55a3c74b69b143 Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Thu, 4 Feb 2016 14:06:43 +0100 Subject: [PATCH 056/139] 8148844: Update run_unit_test macro for InternalVMTests Reviewed-by: sjohanss, david --- .../share/vm/utilities/internalVMTests.cpp | 137 ++++++------------ .../share/vm/utilities/internalVMTests.hpp | 1 + 2 files changed, 48 insertions(+), 90 deletions(-) diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index d74223eb791..7b20c0b6e09 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -30,105 +30,62 @@ #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#define run_unit_test(unit_test_function_call) \ - tty->print_cr("Running test: " #unit_test_function_call); \ - unit_test_function_call +#define run_unit_test(unit_test_function_call) \ + void unit_test_function_call(); \ + run_test(#unit_test_function_call, unit_test_function_call); -// Forward declaration -void TestDependencyContext_test(); -void test_semaphore(); -void TestOS_test(); -void TestReservedSpace_test(); -void TestReserveMemorySpecial_test(); -void TestVirtualSpace_test(); -void TestMetaspaceAux_test(); -void TestMetachunk_test(); -void TestVirtualSpaceNode_test(); -void TestNewSize_test(); -void TestOldSize_test(); -void TestKlass_test(); -void TestBitMap_test(); -void TestAsUtf8(); -void Test_linked_list(); -void TestResourcehash_test(); -void TestChunkedList_test(); -void Test_log_length(); -void Test_configure_stdout(); -void Test_TempNewSymbol(); -void GlobalDefinitions_test(); -void GCTimer_test(); -void arrayOopDesc_test(); -void CollectedHeap_test(); -void QuickSort_test(); -void GuardedMemory_test(); -void AltHashing_test(); -void ObjectMonitor_test(); -void JSON_test(); -void DirectivesParser_test(); - -#if INCLUDE_VM_STRUCTS -void VMStructs_test(); -#endif - -#if INCLUDE_ALL_GCS -void TestOldFreeSpaceCalculation_test(); -void TestG1BiasedArray_test(); -void TestBufferingOopClosure_test(); -void TestCodeCacheRemSet_test(); -void FreeRegionList_test(); -void IHOP_test(); -void test_memset_with_concurrent_readers(); -void TestPredictions_test(); -void WorkerDataArray_test(); -#endif +void InternalVMTests::run_test(const char* name, void (*test)()) { + tty->print_cr("Running test: %s", name); + test(); +} void InternalVMTests::run() { tty->print_cr("Running internal VM tests"); - run_unit_test(TestDependencyContext_test()); - run_unit_test(test_semaphore()); - run_unit_test(TestOS_test()); - run_unit_test(TestReservedSpace_test()); - run_unit_test(TestReserveMemorySpecial_test()); - run_unit_test(TestVirtualSpace_test()); - run_unit_test(TestMetaspaceAux_test()); - run_unit_test(TestMetachunk_test()); - run_unit_test(TestVirtualSpaceNode_test()); - run_unit_test(GlobalDefinitions_test()); - run_unit_test(GCTimer_test()); - run_unit_test(arrayOopDesc_test()); - run_unit_test(CollectedHeap_test()); - run_unit_test(QuickSort_test()); - run_unit_test(GuardedMemory_test()); - run_unit_test(AltHashing_test()); - run_unit_test(TestNewSize_test()); - run_unit_test(TestOldSize_test()); - run_unit_test(TestKlass_test()); - run_unit_test(TestBitMap_test()); - run_unit_test(TestAsUtf8()); - run_unit_test(TestResourcehash_test()); - run_unit_test(ObjectMonitor_test()); - run_unit_test(Test_linked_list()); - run_unit_test(TestChunkedList_test()); - run_unit_test(JSON_test()); - run_unit_test(Test_log_length()); - run_unit_test(Test_configure_stdout()); - run_unit_test(DirectivesParser_test()); - run_unit_test(Test_TempNewSymbol()); + run_unit_test(TestDependencyContext_test); + run_unit_test(test_semaphore); + run_unit_test(TestOS_test); + run_unit_test(TestReservedSpace_test); + run_unit_test(TestReserveMemorySpecial_test); + run_unit_test(TestVirtualSpace_test); + run_unit_test(TestMetaspaceAux_test); + run_unit_test(TestMetachunk_test); + run_unit_test(TestVirtualSpaceNode_test); + run_unit_test(GlobalDefinitions_test); + run_unit_test(GCTimer_test); + run_unit_test(arrayOopDesc_test); + run_unit_test(CollectedHeap_test); + run_unit_test(QuickSort_test); + run_unit_test(GuardedMemory_test); + run_unit_test(AltHashing_test); + run_unit_test(TestNewSize_test); + run_unit_test(TestOldSize_test); + run_unit_test(TestKlass_test); + run_unit_test(TestBitMap_test); + run_unit_test(TestAsUtf8); + run_unit_test(TestResourcehash_test); + run_unit_test(ObjectMonitor_test); + run_unit_test(Test_linked_list); + run_unit_test(TestChunkedList_test); + run_unit_test(JSON_test); + run_unit_test(Test_log_length); + run_unit_test(Test_configure_stdout); + run_unit_test(DirectivesParser_test); + run_unit_test(Test_TempNewSymbol); #if INCLUDE_VM_STRUCTS - run_unit_test(VMStructs_test()); + run_unit_test(VMStructs_test); #endif #if INCLUDE_ALL_GCS - run_unit_test(TestOldFreeSpaceCalculation_test()); - run_unit_test(TestG1BiasedArray_test()); - run_unit_test(TestBufferingOopClosure_test()); - run_unit_test(TestCodeCacheRemSet_test()); + run_unit_test(TestOldFreeSpaceCalculation_test); + run_unit_test(TestG1BiasedArray_test); + run_unit_test(TestBufferingOopClosure_test); + run_unit_test(TestCodeCacheRemSet_test); if (UseG1GC) { - run_unit_test(FreeRegionList_test()); - run_unit_test(IHOP_test()); + run_unit_test(FreeRegionList_test); + run_unit_test(IHOP_test); } - run_unit_test(test_memset_with_concurrent_readers()); - run_unit_test(TestPredictions_test()); - run_unit_test(WorkerDataArray_test()); + run_unit_test(test_memset_with_concurrent_readers); + run_unit_test(TestPredictions_test); + run_unit_test(WorkerDataArray_test); #endif tty->print_cr("All internal VM tests passed"); } diff --git a/hotspot/src/share/vm/utilities/internalVMTests.hpp b/hotspot/src/share/vm/utilities/internalVMTests.hpp index 93bc3309abe..f12a1685802 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.hpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.hpp @@ -30,6 +30,7 @@ #include "memory/allocation.hpp" class InternalVMTests : public AllStatic { + static void run_test(const char* name, void (*test)()); public: static void run(); }; From 969708b2025105e049cc21bbf989a28b0070316c Mon Sep 17 00:00:00 2001 From: David Simms Date: Thu, 4 Feb 2016 18:28:52 +0100 Subject: [PATCH 057/139] 8138562: Event based tracing should cover monitor inflation Reviewed-by: dcubed, egahlin, mgronlun --- hotspot/src/share/vm/runtime/synchronizer.cpp | 92 ++++++++++++++++--- hotspot/src/share/vm/runtime/synchronizer.hpp | 15 ++- hotspot/src/share/vm/trace/trace.xml | 7 ++ .../src/share/vm/trace/traceEventClasses.xsl | 3 +- hotspot/src/share/vm/trace/tracetypes.xml | 9 +- 5 files changed, 109 insertions(+), 17 deletions(-) diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 971012fbb11..7203ff9fbe7 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -42,6 +42,8 @@ #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vframe.hpp" +#include "trace/traceMacros.hpp" +#include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/preserveException.hpp" @@ -130,6 +132,10 @@ static volatile intptr_t gListLock = 0; // protects global monitor lists static volatile int gMonitorFreeCount = 0; // # on gFreeList static volatile int gMonitorPopulation = 0; // # Extant -- in circulation +static void post_monitor_inflate_event(EventJavaMonitorInflate&, + const oop, + const ObjectSynchronizer::InflateCause); + #define CHAINMARKER (cast_to_oop(-1)) @@ -304,7 +310,9 @@ void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) { } } - ObjectSynchronizer::inflate(THREAD, object)->exit(true, THREAD); + ObjectSynchronizer::inflate(THREAD, + object, + inflate_cause_vm_internal)->exit(true, THREAD); } // ----------------------------------------------------------------------------- @@ -338,7 +346,9 @@ void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) { // must be non-zero to avoid looking like a re-entrant lock, // and must not look locked either. lock->set_displaced_header(markOopDesc::unused_mark()); - ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD); + ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_monitor_enter)->enter(THREAD); } // This routine is used to handle interpreter/compiler slow case @@ -368,7 +378,9 @@ intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) { assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } - ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj()); + ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_vm_internal); return monitor->complete_exit(THREAD); } @@ -381,7 +393,9 @@ void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) { assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } - ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj()); + ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_vm_internal); monitor->reenter(recursion, THREAD); } @@ -396,7 +410,7 @@ void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) { assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } THREAD->set_current_pending_monitor_is_from_java(false); - ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD); + ObjectSynchronizer::inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD); THREAD->set_current_pending_monitor_is_from_java(true); } @@ -410,7 +424,9 @@ void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) { } assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); - ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj); + ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, + obj, + inflate_cause_jni_exit); // If this thread has locked the object, exit the monitor. Note: can't use // monitor->check(CHECK); must exit even if an exception is pending. if (monitor->check(THREAD)) { @@ -453,7 +469,10 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { TEVENT(wait - throw IAX); THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } - ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj()); + ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_wait); + DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis); monitor->wait(millis, true, THREAD); @@ -473,7 +492,9 @@ void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) { TEVENT(wait - throw IAX); THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } - ObjectSynchronizer::inflate(THREAD, obj()) -> wait(millis, false, THREAD); + ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_wait)->wait(millis, false, THREAD); } void ObjectSynchronizer::notify(Handle obj, TRAPS) { @@ -486,7 +507,9 @@ void ObjectSynchronizer::notify(Handle obj, TRAPS) { if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) { return; } - ObjectSynchronizer::inflate(THREAD, obj())->notify(THREAD); + ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_notify)->notify(THREAD); } // NOTE: see comment of notify() @@ -500,7 +523,9 @@ void ObjectSynchronizer::notifyall(Handle obj, TRAPS) { if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) { return; } - ObjectSynchronizer::inflate(THREAD, obj())->notifyAll(THREAD); + ObjectSynchronizer::inflate(THREAD, + obj(), + inflate_cause_notify)->notifyAll(THREAD); } // ----------------------------------------------------------------------------- @@ -749,7 +774,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) { } // Inflate the monitor to set hash code - monitor = ObjectSynchronizer::inflate(Self, obj); + monitor = ObjectSynchronizer::inflate(Self, obj, inflate_cause_hash_code); // Load displaced header and check it has hash code mark = monitor->header(); assert(mark->is_neutral(), "invariant"); @@ -1283,17 +1308,22 @@ ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) { assert(mark->monitor()->header()->is_neutral(), "monitor must record a good object header"); return mark->monitor(); } - return ObjectSynchronizer::inflate(Thread::current(), obj); + return ObjectSynchronizer::inflate(Thread::current(), + obj, + inflate_cause_vm_internal); } - ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self, - oop object) { + oop object, + const InflateCause cause) { + // Inflate mutates the heap ... // Relaxing assertion for bug 6320749. assert(Universe::verify_in_progress() || !SafepointSynchronize::is_at_safepoint(), "invariant"); + EventJavaMonitorInflate event; + for (;;) { const markOop mark = object->mark(); assert(!mark->has_bias_pattern(), "invariant"); @@ -1311,6 +1341,7 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self, assert(inf->header()->is_neutral(), "invariant"); assert(inf->object() == object, "invariant"); assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid"); + event.cancel(); // let's not post an inflation event, unless we did the deed ourselves return inf; } @@ -1423,6 +1454,9 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self, object->klass()->external_name()); } } + if (event.should_commit()) { + post_monitor_inflate_event(event, object, cause); + } return m; } @@ -1471,6 +1505,9 @@ ObjectMonitor * NOINLINE ObjectSynchronizer::inflate(Thread * Self, object->klass()->external_name()); } } + if (event.should_commit()) { + post_monitor_inflate_event(event, object, cause); + } return m; } } @@ -1742,6 +1779,33 @@ void ObjectSynchronizer::release_monitors_owned_by_thread(TRAPS) { THREAD->clear_pending_exception(); } +const char* ObjectSynchronizer::inflate_cause_name(const InflateCause cause) { + switch (cause) { + case inflate_cause_vm_internal: return "VM Internal"; + case inflate_cause_monitor_enter: return "Monitor Enter"; + case inflate_cause_wait: return "Monitor Wait"; + case inflate_cause_notify: return "Monitor Notify"; + case inflate_cause_hash_code: return "Monitor Hash Code"; + case inflate_cause_jni_enter: return "JNI Monitor Enter"; + case inflate_cause_jni_exit: return "JNI Monitor Exit"; + default: + ShouldNotReachHere(); + } + return "Unknown"; +} + +static void post_monitor_inflate_event(EventJavaMonitorInflate& event, + const oop obj, + const ObjectSynchronizer::InflateCause cause) { +#if INCLUDE_TRACE + assert(event.should_commit(), "check outside"); + event.set_klass(obj->klass()); + event.set_address((TYPE_ADDRESS)(uintptr_t)(void*)obj); + event.set_cause((u1)cause); + event.commit(); +#endif +} + //------------------------------------------------------------------------------ // Debugging code diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index 0d577bf3303..ab3d145842c 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -42,6 +42,18 @@ class ObjectSynchronizer : AllStatic { owner_none, owner_other } LockOwnership; + + typedef enum { + inflate_cause_vm_internal = 0, + inflate_cause_monitor_enter = 1, + inflate_cause_wait = 2, + inflate_cause_notify = 3, + inflate_cause_hash_code = 4, + inflate_cause_jni_enter = 5, + inflate_cause_jni_exit = 6, + inflate_cause_nof = 7 // Number of causes + } InflateCause; + // exit must be implemented non-blocking, since the compiler cannot easily handle // deoptimization at monitor exit. Hence, it does not take a Handle argument. @@ -94,9 +106,10 @@ class ObjectSynchronizer : AllStatic { static void omFlush(Thread * Self); // Inflate light weight monitor to heavy weight monitor - static ObjectMonitor* inflate(Thread * Self, oop obj); + static ObjectMonitor* inflate(Thread * Self, oop obj, const InflateCause cause); // This version is only for internal use static ObjectMonitor* inflate_helper(oop obj); + static const char* inflate_cause_name(const InflateCause cause); // Returns the identity hash value for an oop // NOTE: It may cause monitor inflation diff --git a/hotspot/src/share/vm/trace/trace.xml b/hotspot/src/share/vm/trace/trace.xml index fdaaaa78b9b..55774fedceb 100644 --- a/hotspot/src/share/vm/trace/trace.xml +++ b/hotspot/src/share/vm/trace/trace.xml @@ -109,6 +109,13 @@ Declares a structure type that can be used in other events. + + + + + + diff --git a/hotspot/src/share/vm/trace/traceEventClasses.xsl b/hotspot/src/share/vm/trace/traceEventClasses.xsl index f7c90ad758f..41d3a446a9e 100644 --- a/hotspot/src/share/vm/trace/traceEventClasses.xsl +++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl @@ -56,7 +56,8 @@ public: void set_endtime(const Ticks& time) {} bool should_commit() const { return false; } static bool is_enabled() { return false; } - void commit() const {} + void commit() {} + void cancel() {} }; diff --git a/hotspot/src/share/vm/trace/tracetypes.xml b/hotspot/src/share/vm/trace/tracetypes.xml index c29831f064c..83b8c7a4acc 100644 --- a/hotspot/src/share/vm/trace/tracetypes.xml +++ b/hotspot/src/share/vm/trace/tracetypes.xml @@ -170,12 +170,16 @@ Now we can use the content + data type in declaring event fields. type="U1" jvm_type="FLAGVALUEORIGIN"> - + + + + @@ -381,5 +385,8 @@ Now we can use the content + data type in declaring event fields. + + From 395a248587b5bd16c3e61c4cefb73799ade0af95 Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Thu, 4 Feb 2016 13:42:18 -0800 Subject: [PATCH 058/139] 8148005: One byte may be corrupted by get_datetime_string() Reviewed-by: dholmes --- hotspot/src/share/vm/utilities/ostream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 2a0fe9e22a6..3bafaec300a 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -380,7 +380,7 @@ extern Mutex* tty_lock; char* get_datetime_string(char *buf, size_t len) { os::local_time_string(buf, len); int i = (int)strlen(buf); - while (i-- >= 0) { + while (--i >= 0) { if (buf[i] == ' ') buf[i] = '_'; else if (buf[i] == ':') buf[i] = '-'; } From 546bba34d73538d62c415286a27f401b2b81798c Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 4 Feb 2016 18:25:02 -0500 Subject: [PATCH 059/139] 8149038: SIGSEGV at frame::is_interpreted_frame_valid -> StubRoutines::SafeFetchN Backout change for 8146984 but add an alignment check which may have caught original bug. Reviewed-by: mgronlun, dcubed --- hotspot/src/share/vm/oops/method.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 2d06a42c10d..7620ea9f985 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -55,7 +55,6 @@ #include "runtime/relocator.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" -#include "runtime/stubRoutines.hpp" #include "utilities/quickSort.hpp" #include "utilities/xmlstream.hpp" @@ -2099,29 +2098,24 @@ void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { } bool Method::has_method_vptr(const void* ptr) { - // Use SafeFetch to check if this is a valid pointer first - // This assumes that the vtbl pointer is the first word of a C++ object. - // This assumption is also in universe.cpp patch_klass_vtable - intptr_t this_vptr = SafeFetchN((intptr_t*)ptr, intptr_t(1)); - if (this_vptr == 1) { - return false; - } Method m; - return (intptr_t)dereference_vptr(&m) == this_vptr; + // This assumes that the vtbl pointer is the first word of a C++ object. + // This assumption is also in universe.cpp patch_klass_vtble + return dereference_vptr(&m) == dereference_vptr(ptr); } // Check that this pointer is valid by checking that the vtbl pointer matches bool Method::is_valid_method() const { if (this == NULL) { return false; - } - - // Quick sanity check on pointer. - if ((intptr_t(this) & (wordSize-1)) != 0) { + } else if ((intptr_t(this) & (wordSize-1)) != 0) { + // Quick sanity check on pointer. return false; + } else if (!is_metaspace_object()) { + return false; + } else { + return has_method_vptr((const void*)this); } - - return has_method_vptr(this); } #ifndef PRODUCT From 1322b0fe56b70750e037414c623f500d218cc7ed Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Fri, 5 Feb 2016 08:59:36 +0100 Subject: [PATCH 060/139] 8149035: Make the full_gc_dump() calls be recorded as part of the GC Reviewed-by: jmasa, sjohanss --- .../vm/gc/cms/concurrentMarkSweepGeneration.cpp | 4 ++++ hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp | 9 +++++---- .../src/share/vm/gc/parallel/psParallelCompact.cpp | 9 +++++---- .../src/share/vm/gc/serial/tenuredGeneration.cpp | 4 ++++ hotspot/src/share/vm/gc/shared/collectedHeap.cpp | 11 ++++------- hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp | 7 ------- hotspot/src/share/vm/logging/logPrefix.hpp | 1 + hotspot/src/share/vm/memory/heapInspection.cpp | 13 +++++-------- hotspot/src/share/vm/memory/heapInspection.hpp | 4 +--- 9 files changed, 29 insertions(+), 33 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index b41a088faa3..d7748d47e71 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -1517,6 +1517,8 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer(); gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start()); + gch->pre_full_gc_dump(gc_timer); + GCTraceTime(Trace, gc) t("CMS:MSC"); // Temporarily widen the span of the weak reference processing to @@ -1593,6 +1595,8 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { _inter_sweep_timer.reset(); _inter_sweep_timer.start(); + gch->post_full_gc_dump(gc_timer); + gc_timer->register_gc_end(); gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); diff --git a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp index 5b93e8a78ca..928aa85bed0 100644 --- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp @@ -156,8 +156,6 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { old_gen->verify_object_start_array(); } - heap->pre_full_gc_dump(_gc_timer); - // Filled in below to track the state of the young gen after the collection. bool eden_empty; bool survivors_empty; @@ -168,6 +166,9 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { GCTraceCPUTime tcpu; GCTraceTime(Info, gc) t("Pause Full", NULL, gc_cause, true); + + heap->pre_full_gc_dump(_gc_timer); + TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); @@ -345,6 +346,8 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { // Track memory usage and detect low memory MemoryService::track_memory_usage(); heap->update_counters(); + + heap->post_full_gc_dump(_gc_timer); } if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) { @@ -367,8 +370,6 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { heap->print_heap_after_gc(); heap->trace_heap_after_gc(_gc_tracer); - heap->post_full_gc_dump(_gc_timer); - #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index b841c32e494..75c67c25b78 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -1746,8 +1746,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { heap->record_gen_tops_before_GC(); } - heap->pre_full_gc_dump(&_gc_timer); - // Make sure data structures are sane, make the heap parsable, and do other // miscellaneous bookkeeping. pre_compact(); @@ -1768,6 +1766,9 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { GCTraceCPUTime tcpu; GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause, true); + + heap->pre_full_gc_dump(&_gc_timer); + TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); @@ -1902,6 +1903,8 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { MemoryService::track_memory_usage(); heap->update_counters(); gc_task_manager()->release_idle_workers(); + + heap->post_full_gc_dump(&_gc_timer); } #ifdef ASSERT @@ -1940,8 +1943,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { collection_exit.ticks()); gc_task_manager()->print_task_time_stamps(); - heap->post_full_gc_dump(&_gc_timer); - #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif diff --git a/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp b/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp index a4958b71d3a..64165542433 100644 --- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp @@ -176,8 +176,12 @@ void TenuredGeneration::collect(bool full, SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer(); gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start()); + gch->pre_full_gc_dump(gc_timer); + GenMarkSweep::invoke_at_safepoint(ref_processor(), clear_all_soft_refs); + gch->post_full_gc_dump(gc_timer); + gc_timer->register_gc_end(); gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp index 8feb5d819b7..9bba8daf55e 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp @@ -572,19 +572,16 @@ void CollectedHeap::resize_all_tlabs() { } void CollectedHeap::full_gc_dump(GCTimer* timer, bool before) { + assert(timer != NULL, "timer is null"); if ((HeapDumpBeforeFullGC && before) || (HeapDumpAfterFullGC && !before)) { - GCIdMarkAndRestore gc_id_mark; - FormatBuffer<> title("Heap Dump (%s full gc)", before ? "before" : "after"); - GCTraceTime(Info, gc) tm(title.buffer(), timer); + GCTraceTime(Info, gc) tm(before ? "Heap Dump (before full gc)" : "Heap Dump (after full gc)", timer); HeapDumper::dump_heap(); } + LogHandle(gc, classhisto) log; if (log.is_trace()) { + GCTraceTime(Trace, gc, classhisto) tm(before ? "Class Histogram (before full gc)" : "Class Histogram (after full gc)", timer); ResourceMark rm; - GCIdMarkAndRestore gc_id_mark; - FormatBuffer<> title("Class Histogram (%s full gc)", - before ? "before" : "after"); - GCTraceTime(Trace, gc, classhisto) tm(title.buffer(), timer); VM_GC_HeapInspection inspector(log.trace_stream(), false /* ! full gc */); inspector.doit(); } diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 647032b25fa..b0d1af971e4 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -481,8 +481,6 @@ void GenCollectedHeap::do_collection(bool full, increment_total_full_collections(); } - pre_full_gc_dump(NULL); // do any pre full gc dumps - if (!prepared_for_verification && run_verification && VerifyGCLevel <= 1 && VerifyBeforeGC) { prepare_for_verify(); @@ -507,11 +505,6 @@ void GenCollectedHeap::do_collection(bool full, // a whole heap collection. complete = complete || collected_old; - if (complete) { // We did a full collection - // FIXME: See comment at pre_full_gc_dump call - post_full_gc_dump(NULL); // do any post full gc dumps - } - print_heap_change(young_prev_used, old_prev_used); MetaspaceAux::print_metaspace_change(metadata_prev_used); diff --git a/hotspot/src/share/vm/logging/logPrefix.hpp b/hotspot/src/share/vm/logging/logPrefix.hpp index 2948e6cddce..039e5f44416 100644 --- a/hotspot/src/share/vm/logging/logPrefix.hpp +++ b/hotspot/src/share/vm/logging/logPrefix.hpp @@ -43,6 +43,7 @@ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, age)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, alloc)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, barrier)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, classhisto)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, compaction)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, compaction, phases)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, cpu)) \ diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index a116650946c..2f8f40d3d71 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -226,9 +226,8 @@ int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title) : - _cit(cit), - _title(title) { +KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit) : + _cit(cit) { _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(_histo_initial_size, true); } @@ -648,7 +647,8 @@ void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats, if (print_stats) { print_class_stats(st, csv_format, columns); } else { - st->print_cr("%s",title()); + st->print_cr(" num #instances #bytes class name"); + st->print_cr("----------------------------------------------"); print_elements(st); } } @@ -729,10 +729,7 @@ void HeapInspection::heap_inspection(outputStream* st) { } // Sort and print klass instance info - const char *title = "\n" - " num #instances #bytes class name\n" - "----------------------------------------------"; - KlassInfoHisto histo(&cit, title); + KlassInfoHisto histo(&cit); HistoClosure hc(&histo); cit.iterate(&hc); diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 7d2acbdb7c9..1ab6baf3336 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -281,8 +281,6 @@ class KlassInfoHisto : public StackObj { KlassInfoTable *_cit; GrowableArray* _elements; GrowableArray* elements() const { return _elements; } - const char* _title; - const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; void print_class_stats(outputStream* st, bool csv_format, const char *columns); @@ -340,7 +338,7 @@ class KlassInfoHisto : public StackObj { } public: - KlassInfoHisto(KlassInfoTable* cit, const char* title); + KlassInfoHisto(KlassInfoTable* cit); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns); From 8776b97706bf1ebe6925e19af4776abedbe1a01e Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Fri, 5 Feb 2016 14:00:58 +0100 Subject: [PATCH 061/139] 8144916: Decrease PerfDataMemorySize back to 32K Reviewed-by: mlarsson, sla --- hotspot/src/share/vm/runtime/globals.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index f257a01a143..95b7bf23c7a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3947,7 +3947,7 @@ public: product(bool, PerfDisableSharedMem, false, \ "Store performance data in standard memory") \ \ - product(intx, PerfDataMemorySize, 64*K, \ + product(intx, PerfDataMemorySize, 32*K, \ "Size of performance data memory region. Will be rounded " \ "up to a multiple of the native os page size.") \ range(128, 32*64*K) \ From b2ab041bf5df94a8e623ef99d042b292f141f606 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 5 Feb 2016 08:14:08 -0500 Subject: [PATCH 062/139] 8148785: Update class file version to 53 for JDK-9 Change max supported class file version to 53 Reviewed-by: alanb, coleenp, shade --- .../share/vm/classfile/classFileParser.cpp | 4 +- .../runtime/classFileParserBug/Class53.jasm | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/runtime/classFileParserBug/Class53.jasm diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 0d693c3890d..a75504d2025 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -80,7 +80,7 @@ #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE #define JAVA_MIN_SUPPORTED_VERSION 45 -#define JAVA_MAX_SUPPORTED_VERSION 52 +#define JAVA_MAX_SUPPORTED_VERSION 53 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 // Used for two backward compatibility reasons: @@ -101,6 +101,8 @@ // Extension method support. #define JAVA_8_VERSION 52 +#define JAVA_9_VERSION 53 + enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream, diff --git a/hotspot/test/runtime/classFileParserBug/Class53.jasm b/hotspot/test/runtime/classFileParserBug/Class53.jasm new file mode 100644 index 00000000000..fa052b48c66 --- /dev/null +++ b/hotspot/test/runtime/classFileParserBug/Class53.jasm @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8148785 + * @summary Check that the JVM accepts class files with version 53 + * @run main Class53 + */ + +super public class Class53 version 53:0 { + + public Method "":"()V" stack 1 locals 1 { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + + public static Method main:"([Ljava/lang/String;)V" stack 0 locals 1 { + return; + } + +} // end Class Class53 From 92143e58faf48fda86595975455c5629182acd0c Mon Sep 17 00:00:00 2001 From: Erik Helin Date: Fri, 5 Feb 2016 16:03:56 +0100 Subject: [PATCH 063/139] 8148973: Rename g1/concurrentMark.{hpp,cpp,inline.hpp} to g1/g1ConcurrentMark.{hpp,cpp,inline.hpp} Reviewed-by: tschatzl, mgerdin --- .../share/vm/gc/g1/concurrentMarkThread.cpp | 16 +- .../share/vm/gc/g1/concurrentMarkThread.hpp | 12 +- .../vm/gc/g1/concurrentMarkThread.inline.hpp | 2 +- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 18 +- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 10 +- .../share/vm/gc/g1/g1CollectedHeap.inline.hpp | 4 +- .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 2 +- ...oncurrentMark.cpp => g1ConcurrentMark.cpp} | 408 +++++++++--------- ...oncurrentMark.hpp => g1ConcurrentMark.hpp} | 124 +++--- ...inline.hpp => g1ConcurrentMark.inline.hpp} | 86 ++-- hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp | 6 +- hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp | 2 +- hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp | 6 +- hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp | 2 +- hotspot/src/share/vm/gc/g1/g1OopClosures.hpp | 20 +- .../share/vm/gc/g1/g1OopClosures.inline.hpp | 2 +- hotspot/src/share/vm/prims/whitebox.cpp | 2 +- 17 files changed, 361 insertions(+), 361 deletions(-) rename hotspot/src/share/vm/gc/g1/{concurrentMark.cpp => g1ConcurrentMark.cpp} (92%) rename hotspot/src/share/vm/gc/g1/{concurrentMark.hpp => g1ConcurrentMark.hpp} (93%) rename hotspot/src/share/vm/gc/g1/{concurrentMark.inline.hpp => g1ConcurrentMark.inline.hpp} (83%) diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index 56753b35673..c41e5befda3 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ SurrogateLockerThread* ConcurrentMarkThread::_slt = NULL; -ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : +ConcurrentMarkThread::ConcurrentMarkThread(G1ConcurrentMark* cm) : ConcurrentGCThread(), _cm(cm), _state(Idle), @@ -56,10 +56,10 @@ ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : class CMCheckpointRootsFinalClosure: public VoidClosure { - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; public: - CMCheckpointRootsFinalClosure(ConcurrentMark* cm) : + CMCheckpointRootsFinalClosure(G1ConcurrentMark* cm) : _cm(cm) {} void do_void(){ @@ -68,10 +68,10 @@ public: }; class CMCleanUp: public VoidClosure { - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; public: - CMCleanUp(ConcurrentMark* cm) : + CMCleanUp(G1ConcurrentMark* cm) : _cm(cm) {} void do_void(){ @@ -92,10 +92,10 @@ void ConcurrentMarkThread::delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool } class GCConcPhaseTimer : StackObj { - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; public: - GCConcPhaseTimer(ConcurrentMark* cm, const char* title) : _cm(cm) { + GCConcPhaseTimer(G1ConcurrentMark* cm, const char* title) : _cm(cm) { _cm->register_concurrent_phase_start(title); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp index 2dd170916da..c75280b8eb3 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,10 @@ #include "gc/shared/concurrentGCThread.hpp" -// The Concurrent Mark GC Thread triggers the parallel CMConcurrentMarkingTasks +// The Concurrent Mark GC Thread triggers the parallel G1CMConcurrentMarkingTasks // as well as handling various marking cleanup. -class ConcurrentMark; +class G1ConcurrentMark; class G1CollectorPolicy; class ConcurrentMarkThread: public ConcurrentGCThread { @@ -45,7 +45,7 @@ class ConcurrentMarkThread: public ConcurrentGCThread { virtual void run(); private: - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; enum State { Idle, @@ -65,7 +65,7 @@ class ConcurrentMarkThread: public ConcurrentGCThread { public: // Constructor - ConcurrentMarkThread(ConcurrentMark* cm); + ConcurrentMarkThread(G1ConcurrentMark* cm); static void makeSurrogateLockerThread(TRAPS); static SurrogateLockerThread* slt() { return _slt; } @@ -75,7 +75,7 @@ class ConcurrentMarkThread: public ConcurrentGCThread { // Marking virtual time so far this thread and concurrent marking tasks. double vtime_mark_accum(); - ConcurrentMark* cm() { return _cm; } + G1ConcurrentMark* cm() { return _cm; } void set_idle() { assert(_state != Started, "must not be starting a new cycle"); _state = Idle; } bool idle() { return _state == Idle; } diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.inline.hpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.inline.hpp index e31475fedd6..bee071b819f 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.inline.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_GC_G1_CONCURRENTMARKTHREAD_INLINE_HPP #define SHARE_VM_GC_G1_CONCURRENTMARKTHREAD_INLINE_HPP -#include "gc/g1/concurrentMark.hpp" #include "gc/g1/concurrentMarkThread.hpp" +#include "gc/g1/g1ConcurrentMark.hpp" // Total virtual time so far. inline double ConcurrentMarkThread::vtime_accum() { diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 142758272f3..d447e3e2c53 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1417,13 +1417,13 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, // Clear the previous marking bitmap, if needed for bitmap verification. // Note we cannot do this when we clear the next marking bitmap in - // ConcurrentMark::abort() above since VerifyDuringGC verifies the + // G1ConcurrentMark::abort() above since VerifyDuringGC verifies the // objects marked during a full GC against the previous bitmap. // But we need to clear it before calling check_bitmaps below since // the full GC has compacted objects and updated TAMS but not updated // the prev bitmap. if (G1VerifyBitmaps) { - ((CMBitMap*) concurrent_mark()->prevMarkBitMap())->clearAll(); + ((G1CMBitMap*) concurrent_mark()->prevMarkBitMap())->clearAll(); } _verifier->check_bitmaps("Full GC End"); @@ -1924,11 +1924,11 @@ jint G1CollectedHeap::initialize() { G1CardCounts::compute_size(g1_rs.size() / HeapWordSize), G1CardCounts::heap_map_factor()); - size_t bitmap_size = CMBitMap::compute_size(g1_rs.size()); + size_t bitmap_size = G1CMBitMap::compute_size(g1_rs.size()); G1RegionToSpaceMapper* prev_bitmap_storage = - create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::heap_map_factor()); + create_aux_memory_mapper("Prev Bitmap", bitmap_size, G1CMBitMap::heap_map_factor()); G1RegionToSpaceMapper* next_bitmap_storage = - create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::heap_map_factor()); + create_aux_memory_mapper("Next Bitmap", bitmap_size, G1CMBitMap::heap_map_factor()); _hrm.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage); g1_barrier_set()->initialize(cardtable_storage); @@ -1960,11 +1960,11 @@ jint G1CollectedHeap::initialize() { _humongous_reclaim_candidates.initialize(start, end, granularity); } - // Create the ConcurrentMark data structure and thread. + // Create the G1ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) - _cm = new ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); + _cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); if (_cm == NULL || !_cm->completed_initialization()) { - vm_shutdown_during_initialization("Could not create/initialize ConcurrentMark"); + vm_shutdown_during_initialization("Could not create/initialize G1ConcurrentMark"); return JNI_ENOMEM; } _cmThread = _cm->cmThread(); @@ -4992,7 +4992,7 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure { G1CollectedHeap* g1h = G1CollectedHeap::heap(); oop obj = (oop)r->bottom(); - CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap(); + G1CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap(); // The following checks whether the humongous object is live are sufficient. // The main additional check (in addition to having a reference from the roots diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 5e8ba970d18..3d8badc27bb 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * 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,11 +25,11 @@ #ifndef SHARE_VM_GC_G1_G1COLLECTEDHEAP_HPP #define SHARE_VM_GC_G1_G1COLLECTEDHEAP_HPP -#include "gc/g1/concurrentMark.hpp" #include "gc/g1/evacuationInfo.hpp" #include "gc/g1/g1AllocationContext.hpp" #include "gc/g1/g1BiasedArray.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1InCSetState.hpp" #include "gc/g1/g1MonitoringSupport.hpp" @@ -68,7 +68,7 @@ class Space; class G1CollectorPolicy; class G1RemSet; class HeapRegionRemSetIterator; -class ConcurrentMark; +class G1ConcurrentMark; class ConcurrentMarkThread; class ConcurrentG1Refine; class ConcurrentGCTimer; @@ -771,7 +771,7 @@ protected: void abandon_collection_set(HeapRegion* cs_head); // The concurrent marker (and the thread it runs in.) - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; ConcurrentMarkThread* _cmThread; // The concurrent refiner. @@ -1380,7 +1380,7 @@ public: inline bool is_obj_ill(const oop obj) const; - ConcurrentMark* concurrent_mark() const { return _cm; } + G1ConcurrentMark* concurrent_mark() const { return _cm; } // Refinement diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index 06143806d59..eaf329b3acd 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,10 @@ #ifndef SHARE_VM_GC_G1_G1COLLECTEDHEAP_INLINE_HPP #define SHARE_VM_GC_G1_G1COLLECTEDHEAP_INLINE_HPP -#include "gc/g1/concurrentMark.hpp" #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index c66db5ed191..a2b949cb417 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -24,10 +24,10 @@ #include "precompiled.hpp" #include "gc/g1/concurrentG1Refine.hpp" -#include "gc/g1/concurrentMark.hpp" #include "gc/g1/concurrentMarkThread.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1IHOPControl.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/heapRegion.inline.hpp" diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp similarity index 92% rename from hotspot/src/share/vm/gc/g1/concurrentMark.cpp rename to hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index a7c70b9483e..4d4ce498e56 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -26,11 +26,11 @@ #include "classfile/metadataOnStackMark.hpp" #include "classfile/symbolTable.hpp" #include "code/codeCache.hpp" -#include "gc/g1/concurrentMark.inline.hpp" #include "gc/g1/concurrentMarkThread.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1StringDedup.hpp" @@ -59,15 +59,15 @@ // Concurrent marking bit map wrapper -CMBitMapRO::CMBitMapRO(int shifter) : +G1CMBitMapRO::G1CMBitMapRO(int shifter) : _bm(), _shifter(shifter) { _bmStartWord = 0; _bmWordSize = 0; } -HeapWord* CMBitMapRO::getNextMarkedWordAddress(const HeapWord* addr, - const HeapWord* limit) const { +HeapWord* G1CMBitMapRO::getNextMarkedWordAddress(const HeapWord* addr, + const HeapWord* limit) const { // First we must round addr *up* to a possible object boundary. addr = (HeapWord*)align_size_up((intptr_t)addr, HeapWordSize << _shifter); @@ -83,7 +83,7 @@ HeapWord* CMBitMapRO::getNextMarkedWordAddress(const HeapWord* addr, } #ifndef PRODUCT -bool CMBitMapRO::covers(MemRegion heap_rs) const { +bool G1CMBitMapRO::covers(MemRegion heap_rs) const { // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize, "size inconsistency"); @@ -92,19 +92,19 @@ bool CMBitMapRO::covers(MemRegion heap_rs) const { } #endif -void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { +void G1CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { _bm.print_on_error(st, prefix); } -size_t CMBitMap::compute_size(size_t heap_size) { +size_t G1CMBitMap::compute_size(size_t heap_size) { return ReservedSpace::allocation_align_size_up(heap_size / mark_distance()); } -size_t CMBitMap::mark_distance() { +size_t G1CMBitMap::mark_distance() { return MinObjAlignmentInBytes * BitsPerByte; } -void CMBitMap::initialize(MemRegion heap, G1RegionToSpaceMapper* storage) { +void G1CMBitMap::initialize(MemRegion heap, G1RegionToSpaceMapper* storage) { _bmStartWord = heap.start(); _bmWordSize = heap.word_size(); @@ -114,7 +114,7 @@ void CMBitMap::initialize(MemRegion heap, G1RegionToSpaceMapper* storage) { storage->set_mapping_changed_listener(&_listener); } -void CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_regions, bool zero_filled) { +void G1CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_regions, bool zero_filled) { if (zero_filled) { return; } @@ -126,11 +126,11 @@ void CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_reg // Closure used for clearing the given mark bitmap. class ClearBitmapHRClosure : public HeapRegionClosure { private: - ConcurrentMark* _cm; - CMBitMap* _bitmap; + G1ConcurrentMark* _cm; + G1CMBitMap* _bitmap; bool _may_yield; // The closure may yield during iteration. If yielded, abort the iteration. public: - ClearBitmapHRClosure(ConcurrentMark* cm, CMBitMap* bitmap, bool may_yield) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap), _may_yield(may_yield) { + ClearBitmapHRClosure(G1ConcurrentMark* cm, G1CMBitMap* bitmap, bool may_yield) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap), _may_yield(may_yield) { assert(!may_yield || cm != NULL, "CM must be non-NULL if this closure is expected to yield."); } @@ -177,7 +177,7 @@ public: } }; -void CMBitMap::clearAll() { +void G1CMBitMap::clearAll() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); ClearBitmapHRClosure cl(NULL, this, false /* may_yield */); uint n_workers = g1h->workers()->active_workers(); @@ -187,7 +187,7 @@ void CMBitMap::clearAll() { return; } -void CMBitMap::clearRange(MemRegion mr) { +void G1CMBitMap::clearRange(MemRegion mr) { mr.intersection(MemRegion(_bmStartWord, _bmWordSize)); assert(!mr.is_empty(), "unexpected empty region"); // convert address range into offset range @@ -195,11 +195,11 @@ void CMBitMap::clearRange(MemRegion mr) { heapWordToOffset(mr.end()), false); } -CMMarkStack::CMMarkStack(ConcurrentMark* cm) : +G1CMMarkStack::G1CMMarkStack(G1ConcurrentMark* cm) : _base(NULL), _cm(cm) {} -bool CMMarkStack::allocate(size_t capacity) { +bool G1CMMarkStack::allocate(size_t capacity) { // allocate a stack of the requisite depth ReservedSpace rs(ReservedSpace::allocation_align_size_up(capacity * sizeof(oop))); if (!rs.is_reserved()) { @@ -214,7 +214,7 @@ bool CMMarkStack::allocate(size_t capacity) { return false; } assert(_virtual_space.committed_size() == rs.size(), - "Didn't reserve backing store for all of ConcurrentMark stack?"); + "Didn't reserve backing store for all of G1ConcurrentMark stack?"); _base = (oop*) _virtual_space.low(); setEmpty(); _capacity = (jint) capacity; @@ -223,7 +223,7 @@ bool CMMarkStack::allocate(size_t capacity) { return true; } -void CMMarkStack::expand() { +void G1CMMarkStack::expand() { // Called, during remark, if we've overflown the marking stack during marking. assert(isEmpty(), "stack should been emptied while handling overflow"); assert(_capacity <= (jint) MarkStackSizeMax, "stack bigger than permitted"); @@ -256,21 +256,21 @@ void CMMarkStack::expand() { } } -void CMMarkStack::set_should_expand() { +void G1CMMarkStack::set_should_expand() { // If we're resetting the marking state because of an // marking stack overflow, record that we should, if // possible, expand the stack. _should_expand = _cm->has_overflown(); } -CMMarkStack::~CMMarkStack() { +G1CMMarkStack::~G1CMMarkStack() { if (_base != NULL) { _base = NULL; _virtual_space.release(); } } -void CMMarkStack::par_push_arr(oop* ptr_arr, int n) { +void G1CMMarkStack::par_push_arr(oop* ptr_arr, int n) { MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); jint start = _index; jint next_index = start + n; @@ -287,7 +287,7 @@ void CMMarkStack::par_push_arr(oop* ptr_arr, int n) { } } -bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) { +bool G1CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) { MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); jint index = _index; if (index == 0) { @@ -305,13 +305,13 @@ bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) { } } -void CMMarkStack::note_start_of_gc() { +void G1CMMarkStack::note_start_of_gc() { assert(_saved_index == -1, "note_start_of_gc()/end_of_gc() bracketed incorrectly"); _saved_index = _index; } -void CMMarkStack::note_end_of_gc() { +void G1CMMarkStack::note_end_of_gc() { // This is intentionally a guarantee, instead of an assert. If we // accidentally add something to the mark stack during GC, it // will be a correctness issue so it's better if we crash. we'll @@ -322,16 +322,16 @@ void CMMarkStack::note_end_of_gc() { _saved_index = -1; } -CMRootRegions::CMRootRegions() : +G1CMRootRegions::G1CMRootRegions() : _young_list(NULL), _cm(NULL), _scan_in_progress(false), _should_abort(false), _next_survivor(NULL) { } -void CMRootRegions::init(G1CollectedHeap* g1h, ConcurrentMark* cm) { +void G1CMRootRegions::init(G1CollectedHeap* g1h, G1ConcurrentMark* cm) { _young_list = g1h->young_list(); _cm = cm; } -void CMRootRegions::prepare_for_scan() { +void G1CMRootRegions::prepare_for_scan() { assert(!scan_in_progress(), "pre-condition"); // Currently, only survivors can be root regions. @@ -341,7 +341,7 @@ void CMRootRegions::prepare_for_scan() { _should_abort = false; } -HeapRegion* CMRootRegions::claim_next() { +HeapRegion* G1CMRootRegions::claim_next() { if (_should_abort) { // If someone has set the should_abort flag, we return NULL to // force the caller to bail out of their loop. @@ -372,7 +372,7 @@ HeapRegion* CMRootRegions::claim_next() { return res; } -void CMRootRegions::scan_finished() { +void G1CMRootRegions::scan_finished() { assert(scan_in_progress(), "pre-condition"); // Currently, only survivors can be root regions. @@ -388,7 +388,7 @@ void CMRootRegions::scan_finished() { } } -bool CMRootRegions::wait_until_scan_finished() { +bool G1CMRootRegions::wait_until_scan_finished() { if (!scan_in_progress()) return false; { @@ -400,11 +400,11 @@ bool CMRootRegions::wait_until_scan_finished() { return true; } -uint ConcurrentMark::scale_parallel_threads(uint n_par_threads) { +uint G1ConcurrentMark::scale_parallel_threads(uint n_par_threads) { return MAX2((n_par_threads + 2) / 4, 1U); } -ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage) : +G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage) : _g1h(g1h), _markBitMap1(), _markBitMap2(), @@ -427,7 +427,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev _max_worker_id(ParallelGCThreads), // _active_tasks set in set_non_marking_state // _tasks set inside the constructor - _task_queues(new CMTaskQueueSet((int) _max_worker_id)), + _task_queues(new G1CMTaskQueueSet((int) _max_worker_id)), _terminator(ParallelTaskTerminator((int) _max_worker_id, _task_queues)), _has_overflown(false), @@ -560,7 +560,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev return; } - _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_worker_id, mtGC); + _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC); @@ -573,17 +573,17 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev uint max_regions = _g1h->max_regions(); for (uint i = 0; i < _max_worker_id; ++i) { - CMTaskQueue* task_queue = new CMTaskQueue(); + G1CMTaskQueue* task_queue = new G1CMTaskQueue(); task_queue->initialize(); _task_queues->register_queue(i, task_queue); _count_card_bitmaps[i] = BitMap(card_bm_size, false); _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC); - _tasks[i] = new CMTask(i, this, - _count_marked_bytes[i], - &_count_card_bitmaps[i], - task_queue, _task_queues); + _tasks[i] = new G1CMTask(i, this, + _count_marked_bytes[i], + &_count_card_bitmaps[i], + task_queue, _task_queues); _accum_task_vtime[i] = 0.0; } @@ -603,7 +603,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev _completed_initialization = true; } -void ConcurrentMark::reset() { +void G1ConcurrentMark::reset() { // Starting values for these two. This should be called in a STW // phase. MemRegion reserved = _g1h->g1_reserved(); @@ -631,7 +631,7 @@ void ConcurrentMark::reset() { } -void ConcurrentMark::reset_marking_state(bool clear_overflow) { +void G1ConcurrentMark::reset_marking_state(bool clear_overflow) { _markStack.set_should_expand(); _markStack.setEmpty(); // Also clears the _markStack overflow flag if (clear_overflow) { @@ -642,12 +642,12 @@ void ConcurrentMark::reset_marking_state(bool clear_overflow) { _finger = _heap_start; for (uint i = 0; i < _max_worker_id; ++i) { - CMTaskQueue* queue = _task_queues->queue(i); + G1CMTaskQueue* queue = _task_queues->queue(i); queue->set_empty(); } } -void ConcurrentMark::set_concurrency(uint active_tasks) { +void G1ConcurrentMark::set_concurrency(uint active_tasks) { assert(active_tasks <= _max_worker_id, "we should not have more"); _active_tasks = active_tasks; @@ -658,7 +658,7 @@ void ConcurrentMark::set_concurrency(uint active_tasks) { _second_overflow_barrier_sync.set_n_workers((int) active_tasks); } -void ConcurrentMark::set_concurrency_and_phase(uint active_tasks, bool concurrent) { +void G1ConcurrentMark::set_concurrency_and_phase(uint active_tasks, bool concurrent) { set_concurrency(active_tasks); _concurrent = concurrent; @@ -679,7 +679,7 @@ void ConcurrentMark::set_concurrency_and_phase(uint active_tasks, bool concurren } } -void ConcurrentMark::set_non_marking_state() { +void G1ConcurrentMark::set_non_marking_state() { // We set the global marking state to some default values when we're // not doing marking. reset_marking_state(); @@ -687,12 +687,12 @@ void ConcurrentMark::set_non_marking_state() { clear_concurrent_marking_in_progress(); } -ConcurrentMark::~ConcurrentMark() { - // The ConcurrentMark instance is never freed. +G1ConcurrentMark::~G1ConcurrentMark() { + // The G1ConcurrentMark instance is never freed. ShouldNotReachHere(); } -void ConcurrentMark::clearNextBitmap() { +void G1ConcurrentMark::clearNextBitmap() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); // Make sure that the concurrent mark thread looks to still be in @@ -721,10 +721,10 @@ void ConcurrentMark::clearNextBitmap() { } class CheckBitmapClearHRClosure : public HeapRegionClosure { - CMBitMap* _bitmap; + G1CMBitMap* _bitmap; bool _error; public: - CheckBitmapClearHRClosure(CMBitMap* bitmap) : _bitmap(bitmap) { + CheckBitmapClearHRClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) { } virtual bool doHeapRegion(HeapRegion* r) { @@ -737,7 +737,7 @@ class CheckBitmapClearHRClosure : public HeapRegionClosure { } }; -bool ConcurrentMark::nextMarkBitmapIsClear() { +bool G1ConcurrentMark::nextMarkBitmapIsClear() { CheckBitmapClearHRClosure cl(_nextMarkBitMap); _g1h->heap_region_iterate(&cl); return cl.complete(); @@ -751,7 +751,7 @@ public: } }; -void ConcurrentMark::checkpointRootsInitialPre() { +void G1ConcurrentMark::checkpointRootsInitialPre() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); @@ -766,7 +766,7 @@ void ConcurrentMark::checkpointRootsInitialPre() { } -void ConcurrentMark::checkpointRootsInitialPost() { +void G1ConcurrentMark::checkpointRootsInitialPost() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); // Start Concurrent Marking weak-reference discovery. @@ -810,7 +810,7 @@ void ConcurrentMark::checkpointRootsInitialPost() { * doesn't manipulate any data structures afterwards. */ -void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { +void G1ConcurrentMark::enter_first_sync_barrier(uint worker_id) { bool barrier_aborted; { SuspendibleThreadSetLeaver sts_leave(concurrent()); @@ -850,16 +850,16 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) { // then go into the second barrier } -void ConcurrentMark::enter_second_sync_barrier(uint worker_id) { +void G1ConcurrentMark::enter_second_sync_barrier(uint worker_id) { SuspendibleThreadSetLeaver sts_leave(concurrent()); _second_overflow_barrier_sync.enter(); // at this point everything should be re-initialized and ready to go } -class CMConcurrentMarkingTask: public AbstractGangTask { +class G1CMConcurrentMarkingTask: public AbstractGangTask { private: - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; ConcurrentMarkThread* _cmt; public: @@ -874,7 +874,7 @@ public: SuspendibleThreadSetJoiner sts_join; assert(worker_id < _cm->active_tasks(), "invariant"); - CMTask* the_task = _cm->task(worker_id); + G1CMTask* the_task = _cm->task(worker_id); the_task->record_start_time(); if (!_cm->has_aborted()) { do { @@ -910,16 +910,16 @@ public: _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime); } - CMConcurrentMarkingTask(ConcurrentMark* cm, - ConcurrentMarkThread* cmt) : + G1CMConcurrentMarkingTask(G1ConcurrentMark* cm, + ConcurrentMarkThread* cmt) : AbstractGangTask("Concurrent Mark"), _cm(cm), _cmt(cmt) { } - ~CMConcurrentMarkingTask() { } + ~G1CMConcurrentMarkingTask() { } }; // Calculates the number of active workers for a concurrent // phase. -uint ConcurrentMark::calc_parallel_marking_threads() { +uint G1ConcurrentMark::calc_parallel_marking_threads() { uint n_conc_workers = 0; if (!UseDynamicNumberOfGCThreads || (!FLAG_IS_DEFAULT(ConcGCThreads) && @@ -939,7 +939,7 @@ uint ConcurrentMark::calc_parallel_marking_threads() { return n_conc_workers; } -void ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { +void G1ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { // Currently, only survivors can be root regions. assert(hr->next_top_at_mark_start() == hr->bottom(), "invariant"); G1RootRegionScanClosure cl(_g1h, this, worker_id); @@ -956,19 +956,19 @@ void ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { } } -class CMRootRegionScanTask : public AbstractGangTask { +class G1CMRootRegionScanTask : public AbstractGangTask { private: - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; public: - CMRootRegionScanTask(ConcurrentMark* cm) : + G1CMRootRegionScanTask(G1ConcurrentMark* cm) : AbstractGangTask("Root Region Scan"), _cm(cm) { } void work(uint worker_id) { assert(Thread::current()->is_ConcurrentGC_thread(), "this should only be done by a conc GC thread"); - CMRootRegions* root_regions = _cm->root_regions(); + G1CMRootRegions* root_regions = _cm->root_regions(); HeapRegion* hr = root_regions->claim_next(); while (hr != NULL) { _cm->scanRootRegion(hr, worker_id); @@ -977,7 +977,7 @@ public: } }; -void ConcurrentMark::scanRootRegions() { +void G1ConcurrentMark::scanRootRegions() { // Start of concurrent marking. ClassLoaderDataGraph::clear_claimed_marks(); @@ -992,7 +992,7 @@ void ConcurrentMark::scanRootRegions() { "Maximum number of marking threads exceeded"); uint active_workers = MAX2(1U, parallel_marking_threads()); - CMRootRegionScanTask task(this); + G1CMRootRegionScanTask task(this); _parallel_workers->set_active_workers(active_workers); _parallel_workers->run_task(&task); @@ -1003,20 +1003,20 @@ void ConcurrentMark::scanRootRegions() { } } -void ConcurrentMark::register_concurrent_phase_start(const char* title) { +void G1ConcurrentMark::register_concurrent_phase_start(const char* title) { assert(!_concurrent_phase_started, "Sanity"); _concurrent_phase_started = true; _g1h->gc_timer_cm()->register_gc_concurrent_start(title); } -void ConcurrentMark::register_concurrent_phase_end() { +void G1ConcurrentMark::register_concurrent_phase_end() { if (_concurrent_phase_started) { _concurrent_phase_started = false; _g1h->gc_timer_cm()->register_gc_concurrent_end(); } } -void ConcurrentMark::markFromRoots() { +void G1ConcurrentMark::markFromRoots() { // we might be tempted to assert that: // assert(asynch == !SafepointSynchronize::is_at_safepoint(), // "inconsistent argument?"); @@ -1037,13 +1037,13 @@ void ConcurrentMark::markFromRoots() { // Parallel task terminator is set in "set_concurrency_and_phase()" set_concurrency_and_phase(active_workers, true /* concurrent */); - CMConcurrentMarkingTask markingTask(this, cmThread()); + G1CMConcurrentMarkingTask markingTask(this, cmThread()); _parallel_workers->set_active_workers(active_workers); _parallel_workers->run_task(&markingTask); print_stats(); } -void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { +void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { // world is stopped at this checkpoint assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped"); @@ -1137,10 +1137,10 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { // Base class of the closures that finalize and verify the // liveness counting data. -class CMCountDataClosureBase: public HeapRegionClosure { +class G1CMCountDataClosureBase: public HeapRegionClosure { protected: G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; CardTableModRefBS* _ct_bs; BitMap* _region_bm; @@ -1155,8 +1155,8 @@ protected: } public: - CMCountDataClosureBase(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm): + G1CMCountDataClosureBase(G1CollectedHeap* g1h, + BitMap* region_bm, BitMap* card_bm): _g1h(g1h), _cm(g1h->concurrent_mark()), _ct_bs(barrier_set_cast(g1h->barrier_set())), _region_bm(region_bm), _card_bm(card_bm) { } @@ -1164,14 +1164,14 @@ public: // Closure that calculates the # live objects per region. Used // for verification purposes during the cleanup pause. -class CalcLiveObjectsClosure: public CMCountDataClosureBase { - CMBitMapRO* _bm; +class CalcLiveObjectsClosure: public G1CMCountDataClosureBase { + G1CMBitMapRO* _bm; size_t _region_marked_bytes; public: - CalcLiveObjectsClosure(CMBitMapRO *bm, G1CollectedHeap* g1h, + CalcLiveObjectsClosure(G1CMBitMapRO *bm, G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) : - CMCountDataClosureBase(g1h, region_bm, card_bm), + G1CMCountDataClosureBase(g1h, region_bm, card_bm), _bm(bm), _region_marked_bytes(0) { } bool doHeapRegion(HeapRegion* hr) { @@ -1264,7 +1264,7 @@ public: class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; CalcLiveObjectsClosure _calc_cl; BitMap* _region_bm; // Region BM to be verified BitMap* _card_bm; // Card BM to be verified @@ -1361,7 +1361,7 @@ public: class G1ParVerifyFinalCountTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; BitMap* _actual_region_bm; BitMap* _actual_card_bm; @@ -1412,12 +1412,12 @@ public: // card liveness bitmap. Also sets the bit for each region, // containing live data, in the region liveness bitmap. -class FinalCountDataUpdateClosure: public CMCountDataClosureBase { +class FinalCountDataUpdateClosure: public G1CMCountDataClosureBase { public: FinalCountDataUpdateClosure(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) : - CMCountDataClosureBase(g1h, region_bm, card_bm) { } + G1CMCountDataClosureBase(g1h, region_bm, card_bm) { } bool doHeapRegion(HeapRegion* hr) { HeapWord* ntams = hr->next_top_at_mark_start(); @@ -1466,7 +1466,7 @@ class FinalCountDataUpdateClosure: public CMCountDataClosureBase { class G1ParFinalCountTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; BitMap* _actual_region_bm; BitMap* _actual_card_bm; @@ -1594,7 +1594,7 @@ public: } }; -void ConcurrentMark::cleanup() { +void G1ConcurrentMark::cleanup() { // world is stopped at this checkpoint assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped"); @@ -1725,7 +1725,7 @@ void ConcurrentMark::cleanup() { g1h->trace_heap_after_concurrent_cycle(); } -void ConcurrentMark::completeCleanup() { +void G1ConcurrentMark::completeCleanup() { if (has_aborted()) return; G1CollectedHeap* g1h = G1CollectedHeap::heap(); @@ -1786,11 +1786,11 @@ bool G1CMIsAliveClosure::do_object_b(oop obj) { } // 'Keep Alive' oop closure used by both serial parallel reference processing. -// Uses the CMTask associated with a worker thread (for serial reference -// processing the CMTask for worker 0 is used) to preserve (mark) and +// Uses the G1CMTask associated with a worker thread (for serial reference +// processing the G1CMTask for worker 0 is used) to preserve (mark) and // trace referent objects. // -// Using the CMTask and embedded local queues avoids having the worker +// Using the G1CMTask and embedded local queues avoids having the worker // threads operating on the global mark stack. This reduces the risk // of overflowing the stack - which we would rather avoid at this late // state. Also using the tasks' local queues removes the potential @@ -1798,13 +1798,13 @@ bool G1CMIsAliveClosure::do_object_b(oop obj) { // operating on the global stack. class G1CMKeepAliveAndDrainClosure: public OopClosure { - ConcurrentMark* _cm; - CMTask* _task; - int _ref_counter_limit; - int _ref_counter; - bool _is_serial; + G1ConcurrentMark* _cm; + G1CMTask* _task; + int _ref_counter_limit; + int _ref_counter; + bool _is_serial; public: - G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task, bool is_serial) : + G1CMKeepAliveAndDrainClosure(G1ConcurrentMark* cm, G1CMTask* task, bool is_serial) : _cm(cm), _task(task), _is_serial(is_serial), _ref_counter_limit(G1RefProcDrainInterval) { assert(_ref_counter_limit > 0, "sanity"); @@ -1824,19 +1824,19 @@ class G1CMKeepAliveAndDrainClosure: public OopClosure { if (_ref_counter == 0) { // We have dealt with _ref_counter_limit references, pushing them // and objects reachable from them on to the local stack (and - // possibly the global stack). Call CMTask::do_marking_step() to + // possibly the global stack). Call G1CMTask::do_marking_step() to // process these entries. // - // We call CMTask::do_marking_step() in a loop, which we'll exit if + // We call G1CMTask::do_marking_step() in a loop, which we'll exit if // there's nothing more to do (i.e. we're done with the entries that - // were pushed as a result of the CMTask::deal_with_reference() calls + // were pushed as a result of the G1CMTask::deal_with_reference() calls // above) or we overflow. // - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // Note: G1CMTask::do_marking_step() can set the G1CMTask::has_aborted() // flag while there may still be some work to do. (See the comment at - // the beginning of CMTask::do_marking_step() for those conditions - + // the beginning of G1CMTask::do_marking_step() for those conditions - // one of which is reaching the specified time target.) It is only - // when CMTask::do_marking_step() returns without setting the + // when G1CMTask::do_marking_step() returns without setting the // has_aborted() flag that the marking step has completed. do { double mark_step_duration_ms = G1ConcMarkStepDurationMillis; @@ -1851,39 +1851,39 @@ class G1CMKeepAliveAndDrainClosure: public OopClosure { }; // 'Drain' oop closure used by both serial and parallel reference processing. -// Uses the CMTask associated with a given worker thread (for serial -// reference processing the CMtask for worker 0 is used). Calls the +// Uses the G1CMTask associated with a given worker thread (for serial +// reference processing the G1CMtask for worker 0 is used). Calls the // do_marking_step routine, with an unbelievably large timeout value, // to drain the marking data structures of the remaining entries // added by the 'keep alive' oop closure above. class G1CMDrainMarkingStackClosure: public VoidClosure { - ConcurrentMark* _cm; - CMTask* _task; - bool _is_serial; + G1ConcurrentMark* _cm; + G1CMTask* _task; + bool _is_serial; public: - G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_serial) : + G1CMDrainMarkingStackClosure(G1ConcurrentMark* cm, G1CMTask* task, bool is_serial) : _cm(cm), _task(task), _is_serial(is_serial) { assert(!_is_serial || _task->worker_id() == 0, "only task 0 for serial code"); } void do_void() { do { - // We call CMTask::do_marking_step() to completely drain the local + // We call G1CMTask::do_marking_step() to completely drain the local // and global marking stacks of entries pushed by the 'keep alive' // oop closure (an instance of G1CMKeepAliveAndDrainClosure above). // - // CMTask::do_marking_step() is called in a loop, which we'll exit + // G1CMTask::do_marking_step() is called in a loop, which we'll exit // if there's nothing more to do (i.e. we've completely drained the // entries that were pushed as a a result of applying the 'keep alive' // closure to the entries on the discovered ref lists) or we overflow // the global marking stack. // - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // Note: G1CMTask::do_marking_step() can set the G1CMTask::has_aborted() // flag while there may still be some work to do. (See the comment at - // the beginning of CMTask::do_marking_step() for those conditions - + // the beginning of G1CMTask::do_marking_step() for those conditions - // one of which is reaching the specified time target.) It is only - // when CMTask::do_marking_step() returns without setting the + // when G1CMTask::do_marking_step() returns without setting the // has_aborted() flag that the marking step has completed. _task->do_marking_step(1000000000.0 /* something very large */, @@ -1898,14 +1898,14 @@ class G1CMDrainMarkingStackClosure: public VoidClosure { class G1CMRefProcTaskExecutor: public AbstractRefProcTaskExecutor { private: - G1CollectedHeap* _g1h; - ConcurrentMark* _cm; - WorkGang* _workers; - uint _active_workers; + G1CollectedHeap* _g1h; + G1ConcurrentMark* _cm; + WorkGang* _workers; + uint _active_workers; public: G1CMRefProcTaskExecutor(G1CollectedHeap* g1h, - ConcurrentMark* cm, + G1ConcurrentMark* cm, WorkGang* workers, uint n_workers) : _g1h(g1h), _cm(cm), @@ -1918,14 +1918,14 @@ public: class G1CMRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; - ProcessTask& _proc_task; - G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + ProcessTask& _proc_task; + G1CollectedHeap* _g1h; + G1ConcurrentMark* _cm; public: G1CMRefProcTaskProxy(ProcessTask& proc_task, - G1CollectedHeap* g1h, - ConcurrentMark* cm) : + G1CollectedHeap* g1h, + G1ConcurrentMark* cm) : AbstractGangTask("Process reference objects in parallel"), _proc_task(proc_task), _g1h(g1h), _cm(cm) { ReferenceProcessor* rp = _g1h->ref_processor_cm(); @@ -1935,7 +1935,7 @@ public: virtual void work(uint worker_id) { ResourceMark rm; HandleMark hm; - CMTask* task = _cm->task(worker_id); + G1CMTask* task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, task, false /* is_serial */); G1CMDrainMarkingStackClosure g1_par_drain(_cm, task, false /* is_serial */); @@ -1952,7 +1952,7 @@ void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { // We need to reset the concurrency level before each // proxy task execution, so that the termination protocol - // and overflow handling in CMTask::do_marking_step() knows + // and overflow handling in G1CMTask::do_marking_step() knows // how many workers to wait for. _cm->set_concurrency(_active_workers); _workers->run_task(&proc_task_proxy); @@ -1982,17 +1982,17 @@ void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { // // We need to reset the concurrency level before each // proxy task execution, so that the termination protocol - // and overflow handling in CMTask::do_marking_step() knows + // and overflow handling in G1CMTask::do_marking_step() knows // how many workers to wait for. _cm->set_concurrency(_active_workers); _workers->run_task(&enq_task_proxy); } -void ConcurrentMark::weakRefsWorkParallelPart(BoolObjectClosure* is_alive, bool purged_classes) { +void G1ConcurrentMark::weakRefsWorkParallelPart(BoolObjectClosure* is_alive, bool purged_classes) { G1CollectedHeap::heap()->parallel_cleaning(is_alive, true, true, purged_classes); } -void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { +void G1ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { if (has_overflown()) { // Skip processing the discovered references if we have // overflown the global marking stack. Reference objects @@ -2127,19 +2127,19 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { } } -void ConcurrentMark::swapMarkBitMaps() { - CMBitMapRO* temp = _prevMarkBitMap; - _prevMarkBitMap = (CMBitMapRO*)_nextMarkBitMap; - _nextMarkBitMap = (CMBitMap*) temp; +void G1ConcurrentMark::swapMarkBitMaps() { + G1CMBitMapRO* temp = _prevMarkBitMap; + _prevMarkBitMap = (G1CMBitMapRO*)_nextMarkBitMap; + _nextMarkBitMap = (G1CMBitMap*) temp; } // Closure for marking entries in SATB buffers. -class CMSATBBufferClosure : public SATBBufferClosure { +class G1CMSATBBufferClosure : public SATBBufferClosure { private: - CMTask* _task; + G1CMTask* _task; G1CollectedHeap* _g1h; - // This is very similar to CMTask::deal_with_reference, but with + // This is very similar to G1CMTask::deal_with_reference, but with // more relaxed requirements for the argument, so this must be more // circumspect about treating the argument as an object. void do_entry(void* entry) const { @@ -2156,7 +2156,7 @@ private: } public: - CMSATBBufferClosure(CMTask* task, G1CollectedHeap* g1h) + G1CMSATBBufferClosure(G1CMTask* task, G1CollectedHeap* g1h) : _task(task), _g1h(g1h) { } virtual void do_buffer(void** buffer, size_t size) { @@ -2167,13 +2167,13 @@ public: }; class G1RemarkThreadsClosure : public ThreadClosure { - CMSATBBufferClosure _cm_satb_cl; + G1CMSATBBufferClosure _cm_satb_cl; G1CMOopClosure _cm_cl; MarkingCodeBlobClosure _code_cl; int _thread_parity; public: - G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task) : + G1RemarkThreadsClosure(G1CollectedHeap* g1h, G1CMTask* task) : _cm_satb_cl(task, g1h), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations), @@ -2202,15 +2202,15 @@ class G1RemarkThreadsClosure : public ThreadClosure { } }; -class CMRemarkTask: public AbstractGangTask { +class G1CMRemarkTask: public AbstractGangTask { private: - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; public: void work(uint worker_id) { // Since all available tasks are actually started, we should // only proceed if we're supposed to be active. if (worker_id < _cm->active_tasks()) { - CMTask* task = _cm->task(worker_id); + G1CMTask* task = _cm->task(worker_id); task->record_start_time(); { ResourceMark rm; @@ -2231,13 +2231,13 @@ public: } } - CMRemarkTask(ConcurrentMark* cm, uint active_workers) : + G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) : AbstractGangTask("Par Remark"), _cm(cm) { _cm->terminator()->reset_for_reuse(active_workers); } }; -void ConcurrentMark::checkpointRootsFinalWork() { +void G1ConcurrentMark::checkpointRootsFinalWork() { ResourceMark rm; HandleMark hm; G1CollectedHeap* g1h = G1CollectedHeap::heap(); @@ -2250,14 +2250,14 @@ void ConcurrentMark::checkpointRootsFinalWork() { uint active_workers = g1h->workers()->active_workers(); set_concurrency_and_phase(active_workers, false /* concurrent */); // Leave _parallel_marking_threads at it's - // value originally calculated in the ConcurrentMark + // value originally calculated in the G1ConcurrentMark // constructor and pass values of the active workers // through the gang in the task. { StrongRootsScope srs(active_workers); - CMRemarkTask remarkTask(this, active_workers); + G1CMRemarkTask remarkTask(this, active_workers); // We will start all available threads, even if we decide that the // active_workers will be fewer. The extra ones will just bail out // immediately. @@ -2274,14 +2274,14 @@ void ConcurrentMark::checkpointRootsFinalWork() { print_stats(); } -void ConcurrentMark::clearRangePrevBitmap(MemRegion mr) { +void G1ConcurrentMark::clearRangePrevBitmap(MemRegion mr) { // Note we are overriding the read-only view of the prev map here, via // the cast. - ((CMBitMap*)_prevMarkBitMap)->clearRange(mr); + ((G1CMBitMap*)_prevMarkBitMap)->clearRange(mr); } HeapRegion* -ConcurrentMark::claim_region(uint worker_id) { +G1ConcurrentMark::claim_region(uint worker_id) { // "checkpoint" the finger HeapWord* finger = _finger; @@ -2350,7 +2350,7 @@ public: } }; -void ConcurrentMark::verify_no_cset_oops() { +void G1ConcurrentMark::verify_no_cset_oops() { assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint"); if (!G1CollectedHeap::heap()->collector_state()->mark_in_progress()) { return; @@ -2361,7 +2361,7 @@ void ConcurrentMark::verify_no_cset_oops() { // Verify entries on the task queues for (uint i = 0; i < _max_worker_id; ++i) { - CMTaskQueue* queue = _task_queues->queue(i); + G1CMTaskQueue* queue = _task_queues->queue(i); queue->iterate(VerifyNoCSetOops("Queue", i)); } @@ -2379,7 +2379,7 @@ void ConcurrentMark::verify_no_cset_oops() { // Verify the task fingers assert(parallel_marking_threads() <= _max_worker_id, "sanity"); for (uint i = 0; i < parallel_marking_threads(); ++i) { - CMTask* task = _tasks[i]; + G1CMTask* task = _tasks[i]; HeapWord* task_finger = task->finger(); if (task_finger != NULL && task_finger < _heap_end) { // See above note on the global finger verification. @@ -2397,7 +2397,7 @@ void ConcurrentMark::verify_no_cset_oops() { // with marking. class AggregateCountDataHRClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; CardTableModRefBS* _ct_bs; BitMap* _cm_card_bm; uint _max_worker_id; @@ -2492,7 +2492,7 @@ class AggregateCountDataHRClosure: public HeapRegionClosure { class G1AggregateCountDataTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; BitMap* _cm_card_bm; uint _max_worker_id; uint _active_workers; @@ -2500,7 +2500,7 @@ protected: public: G1AggregateCountDataTask(G1CollectedHeap* g1h, - ConcurrentMark* cm, + G1ConcurrentMark* cm, BitMap* cm_card_bm, uint max_worker_id, uint n_workers) : @@ -2519,7 +2519,7 @@ public: }; -void ConcurrentMark::aggregate_count_data() { +void G1ConcurrentMark::aggregate_count_data() { uint n_workers = _g1h->workers()->active_workers(); G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, @@ -2529,7 +2529,7 @@ void ConcurrentMark::aggregate_count_data() { } // Clear the per-worker arrays used to store the per-region counting data -void ConcurrentMark::clear_all_count_data() { +void G1ConcurrentMark::clear_all_count_data() { // Clear the global card bitmap - it will be filled during // liveness count aggregation (during remark) and the // final counting task. @@ -2554,7 +2554,7 @@ void ConcurrentMark::clear_all_count_data() { } } -void ConcurrentMark::print_stats() { +void G1ConcurrentMark::print_stats() { if (!log_is_enabled(Debug, gc, stats)) { return; } @@ -2566,7 +2566,7 @@ void ConcurrentMark::print_stats() { } // abandon current marking iteration due to a Full GC -void ConcurrentMark::abort() { +void G1ConcurrentMark::abort() { if (!cmThread()->during_cycle() || _has_aborted) { // We haven't started a concurrent cycle or we have already aborted it. No need to do anything. return; @@ -2617,7 +2617,7 @@ static void print_ms_time_info(const char* prefix, const char* name, } } -void ConcurrentMark::print_summary_info() { +void G1ConcurrentMark::print_summary_info() { LogHandle(gc, marking) log; if (!log.is_trace()) { return; @@ -2644,11 +2644,11 @@ void ConcurrentMark::print_summary_info() { cmThread()->vtime_accum(), cmThread()->vtime_mark_accum()); } -void ConcurrentMark::print_worker_threads_on(outputStream* st) const { +void G1ConcurrentMark::print_worker_threads_on(outputStream* st) const { _parallel_workers->print_worker_threads_on(st); } -void ConcurrentMark::print_on_error(outputStream* st) const { +void G1ConcurrentMark::print_on_error(outputStream* st) const { st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, p2i(_prevMarkBitMap), p2i(_nextMarkBitMap)); _prevMarkBitMap->print_on_error(st, " Prev Bits: "); @@ -2656,7 +2656,7 @@ void ConcurrentMark::print_on_error(outputStream* st) const { } // We take a break if someone is trying to stop the world. -bool ConcurrentMark::do_yield_check(uint worker_id) { +bool G1ConcurrentMark::do_yield_check(uint worker_id) { if (SuspendibleThreadSet::should_yield()) { if (worker_id == 0) { _g1h->g1_policy()->record_concurrent_pause(); @@ -2669,15 +2669,15 @@ bool ConcurrentMark::do_yield_check(uint worker_id) { } // Closure for iteration over bitmaps -class CMBitMapClosure : public BitMapClosure { +class G1CMBitMapClosure : public BitMapClosure { private: // the bitmap that is being iterated over - CMBitMap* _nextMarkBitMap; - ConcurrentMark* _cm; - CMTask* _task; + G1CMBitMap* _nextMarkBitMap; + G1ConcurrentMark* _cm; + G1CMTask* _task; public: - CMBitMapClosure(CMTask *task, ConcurrentMark* cm, CMBitMap* nextMarkBitMap) : + G1CMBitMapClosure(G1CMTask *task, G1ConcurrentMark* cm, G1CMBitMap* nextMarkBitMap) : _task(task), _cm(cm), _nextMarkBitMap(nextMarkBitMap) { } bool do_bit(size_t offset) { @@ -2710,13 +2710,13 @@ static ReferenceProcessor* get_cm_oop_closure_ref_processor(G1CollectedHeap* g1h } G1CMOopClosure::G1CMOopClosure(G1CollectedHeap* g1h, - ConcurrentMark* cm, - CMTask* task) + G1ConcurrentMark* cm, + G1CMTask* task) : MetadataAwareOopClosure(get_cm_oop_closure_ref_processor(g1h)), _g1h(g1h), _cm(cm), _task(task) { } -void CMTask::setup_for_region(HeapRegion* hr) { +void G1CMTask::setup_for_region(HeapRegion* hr) { assert(hr != NULL, "claim_region() should have filtered out NULL regions"); _curr_region = hr; @@ -2724,7 +2724,7 @@ void CMTask::setup_for_region(HeapRegion* hr) { update_region_limit(); } -void CMTask::update_region_limit() { +void G1CMTask::update_region_limit() { HeapRegion* hr = _curr_region; HeapWord* bottom = hr->bottom(); HeapWord* limit = hr->next_top_at_mark_start(); @@ -2756,12 +2756,12 @@ void CMTask::update_region_limit() { _region_limit = limit; } -void CMTask::giveup_current_region() { +void G1CMTask::giveup_current_region() { assert(_curr_region != NULL, "invariant"); clear_region_fields(); } -void CMTask::clear_region_fields() { +void G1CMTask::clear_region_fields() { // Values for these three fields that indicate that we're not // holding on to a region. _curr_region = NULL; @@ -2769,7 +2769,7 @@ void CMTask::clear_region_fields() { _region_limit = NULL; } -void CMTask::set_cm_oop_closure(G1CMOopClosure* cm_oop_closure) { +void G1CMTask::set_cm_oop_closure(G1CMOopClosure* cm_oop_closure) { if (cm_oop_closure == NULL) { assert(_cm_oop_closure != NULL, "invariant"); } else { @@ -2778,7 +2778,7 @@ void CMTask::set_cm_oop_closure(G1CMOopClosure* cm_oop_closure) { _cm_oop_closure = cm_oop_closure; } -void CMTask::reset(CMBitMap* nextMarkBitMap) { +void G1CMTask::reset(G1CMBitMap* nextMarkBitMap) { guarantee(nextMarkBitMap != NULL, "invariant"); _nextMarkBitMap = nextMarkBitMap; clear_region_fields(); @@ -2789,7 +2789,7 @@ void CMTask::reset(CMBitMap* nextMarkBitMap) { _termination_start_time_ms = 0.0; } -bool CMTask::should_exit_termination() { +bool G1CMTask::should_exit_termination() { regular_clock_call(); // This is called when we are in the termination protocol. We should // quit if, for some reason, this task wants to abort or the global @@ -2797,14 +2797,14 @@ bool CMTask::should_exit_termination() { return !_cm->mark_stack_empty() || has_aborted(); } -void CMTask::reached_limit() { +void G1CMTask::reached_limit() { assert(_words_scanned >= _words_scanned_limit || _refs_reached >= _refs_reached_limit , "shouldn't have been called otherwise"); regular_clock_call(); } -void CMTask::regular_clock_call() { +void G1CMTask::regular_clock_call() { if (has_aborted()) return; // First, we need to recalculate the words scanned and refs reached @@ -2860,7 +2860,7 @@ void CMTask::regular_clock_call() { } } -void CMTask::recalculate_limits() { +void G1CMTask::recalculate_limits() { _real_words_scanned_limit = _words_scanned + words_scanned_period; _words_scanned_limit = _real_words_scanned_limit; @@ -2868,7 +2868,7 @@ void CMTask::recalculate_limits() { _refs_reached_limit = _real_refs_reached_limit; } -void CMTask::decrease_limits() { +void G1CMTask::decrease_limits() { // This is called when we believe that we're going to do an infrequent // operation which will increase the per byte scanned cost (i.e. move // entries to/from the global stack). It basically tries to decrease the @@ -2880,7 +2880,7 @@ void CMTask::decrease_limits() { 3 * refs_reached_period / 4; } -void CMTask::move_entries_to_global_stack() { +void G1CMTask::move_entries_to_global_stack() { // local array where we'll store the entries that will be popped // from the local queue oop buffer[global_stack_transfer_size]; @@ -2904,7 +2904,7 @@ void CMTask::move_entries_to_global_stack() { decrease_limits(); } -void CMTask::get_entries_from_global_stack() { +void G1CMTask::get_entries_from_global_stack() { // local array where we'll store the entries that will be popped // from the global stack. oop buffer[global_stack_transfer_size]; @@ -2926,7 +2926,7 @@ void CMTask::get_entries_from_global_stack() { decrease_limits(); } -void CMTask::drain_local_queue(bool partially) { +void G1CMTask::drain_local_queue(bool partially) { if (has_aborted()) return; // Decide what the target size is, depending whether we're going to @@ -2958,7 +2958,7 @@ void CMTask::drain_local_queue(bool partially) { } } -void CMTask::drain_global_stack(bool partially) { +void G1CMTask::drain_global_stack(bool partially) { if (has_aborted()) return; // We have a policy to drain the local queue before we attempt to @@ -2990,7 +2990,7 @@ void CMTask::drain_global_stack(bool partially) { // non-par versions of the methods. this is why some of the code is // replicated. We should really get rid of the single-threaded version // of the code to simplify things. -void CMTask::drain_satb_buffers() { +void G1CMTask::drain_satb_buffers() { if (has_aborted()) return; // We set this so that the regular clock knows that we're in the @@ -2999,7 +2999,7 @@ void CMTask::drain_satb_buffers() { // very counter productive if it did that. :-) _draining_satb_buffers = true; - CMSATBBufferClosure satb_cl(this, _g1h); + G1CMSATBBufferClosure satb_cl(this, _g1h); SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); // This keeps claiming and applying the closure to completed buffers @@ -3020,7 +3020,7 @@ void CMTask::drain_satb_buffers() { decrease_limits(); } -void CMTask::print_stats() { +void G1CMTask::print_stats() { log_debug(gc, stats)("Marking Stats, task = %u, calls = %d", _worker_id, _calls); log_debug(gc, stats)(" Elapsed time = %1.2lfms, Termination time = %1.2lfms", @@ -3032,7 +3032,7 @@ void CMTask::print_stats() { _step_times_ms.maximum(), _step_times_ms.sum()); } -bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) { +bool G1ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) { return _task_queues->steal(worker_id, hash_seed, obj); } @@ -3151,9 +3151,9 @@ bool ConcurrentMark::try_stealing(uint worker_id, int* hash_seed, oop& obj) { *****************************************************************************/ -void CMTask::do_marking_step(double time_target_ms, - bool do_termination, - bool is_serial) { +void G1CMTask::do_marking_step(double time_target_ms, + bool do_termination, + bool is_serial) { assert(time_target_ms >= 1.0, "minimum granularity is 1ms"); assert(concurrent() == _cm->concurrent(), "they should be the same"); @@ -3174,7 +3174,7 @@ void CMTask::do_marking_step(double time_target_ms, _start_time_ms = os::elapsedVTime() * 1000.0; // If do_stealing is true then do_marking_step will attempt to - // steal work from the other CMTasks. It only makes sense to + // steal work from the other G1CMTasks. It only makes sense to // enable stealing when the termination protocol is enabled // and do_marking_step() is not being called serially. bool do_stealing = do_termination && !is_serial; @@ -3198,8 +3198,8 @@ void CMTask::do_marking_step(double time_target_ms, // Set up the bitmap and oop closures. Anything that uses them is // eventually called from this method, so it is OK to allocate these // statically. - CMBitMapClosure bitmap_closure(this, _cm, _nextMarkBitMap); - G1CMOopClosure cm_oop_closure(_g1h, _cm, this); + G1CMBitMapClosure bitmap_closure(this, _cm, _nextMarkBitMap); + G1CMOopClosure cm_oop_closure(_g1h, _cm, this); set_cm_oop_closure(&cm_oop_closure); if (_cm->has_overflown()) { @@ -3382,7 +3382,7 @@ void CMTask::do_marking_step(double time_target_ms, assert(_task_queue->size() == 0, "only way to reach here"); _termination_start_time_ms = os::elapsedVTime() * 1000.0; - // The CMTask class also extends the TerminatorTerminator class, + // The G1CMTask class also extends the TerminatorTerminator class, // hence its should_exit_termination() method will also decide // whether to exit the termination protocol or not. bool finished = (is_serial || @@ -3475,12 +3475,12 @@ void CMTask::do_marking_step(double time_target_ms, _claimed = false; } -CMTask::CMTask(uint worker_id, - ConcurrentMark* cm, - size_t* marked_bytes, - BitMap* card_bm, - CMTaskQueue* task_queue, - CMTaskQueueSet* task_queues) +G1CMTask::G1CMTask(uint worker_id, + G1ConcurrentMark* cm, + size_t* marked_bytes, + BitMap* card_bm, + G1CMTaskQueue* task_queue, + G1CMTaskQueueSet* task_queues) : _g1h(G1CollectedHeap::heap()), _worker_id(worker_id), _cm(cm), _claimed(false), diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp similarity index 93% rename from hotspot/src/share/vm/gc/g1/concurrentMark.hpp rename to hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 5c8f81e78df..0cce8b70d61 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -22,8 +22,8 @@ * */ -#ifndef SHARE_VM_GC_G1_CONCURRENTMARK_HPP -#define SHARE_VM_GC_G1_CONCURRENTMARK_HPP +#ifndef SHARE_VM_GC_G1_G1CONCURRENTMARK_HPP +#define SHARE_VM_GC_G1_G1CONCURRENTMARK_HPP #include "classfile/javaClasses.hpp" #include "gc/g1/g1RegionToSpaceMapper.hpp" @@ -31,11 +31,11 @@ #include "gc/shared/taskqueue.hpp" class G1CollectedHeap; -class CMBitMap; -class CMTask; -class ConcurrentMark; -typedef GenericTaskQueue CMTaskQueue; -typedef GenericTaskQueueSet CMTaskQueueSet; +class G1CMBitMap; +class G1CMTask; +class G1ConcurrentMark; +typedef GenericTaskQueue G1CMTaskQueue; +typedef GenericTaskQueueSet G1CMTaskQueueSet; // Closure used by CM during concurrent reference discovery // and reference processing (during remarking) to determine @@ -54,7 +54,7 @@ class G1CMIsAliveClosure: public BoolObjectClosure { // A generic CM bit map. This is essentially a wrapper around the BitMap // class, with one bit per (1<<_shifter) HeapWords. -class CMBitMapRO VALUE_OBJ_CLASS_SPEC { +class G1CMBitMapRO VALUE_OBJ_CLASS_SPEC { protected: HeapWord* _bmStartWord; // base address of range covered by map size_t _bmWordSize; // map size (in #HeapWords covered) @@ -63,7 +63,7 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { public: // constructor - CMBitMapRO(int shifter); + G1CMBitMapRO(int shifter); // inquiries HeapWord* startWord() const { return _bmStartWord; } @@ -104,20 +104,20 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { NOT_PRODUCT(bool covers(MemRegion rs) const;) }; -class CMBitMapMappingChangedListener : public G1MappingChangedListener { +class G1CMBitMapMappingChangedListener : public G1MappingChangedListener { private: - CMBitMap* _bm; + G1CMBitMap* _bm; public: - CMBitMapMappingChangedListener() : _bm(NULL) {} + G1CMBitMapMappingChangedListener() : _bm(NULL) {} - void set_bitmap(CMBitMap* bm) { _bm = bm; } + void set_bitmap(G1CMBitMap* bm) { _bm = bm; } virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); }; -class CMBitMap : public CMBitMapRO { +class G1CMBitMap : public G1CMBitMapRO { private: - CMBitMapMappingChangedListener _listener; + G1CMBitMapMappingChangedListener _listener; public: static size_t compute_size(size_t heap_size); @@ -129,7 +129,7 @@ class CMBitMap : public CMBitMapRO { return mark_distance(); } - CMBitMap() : CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); } + G1CMBitMap() : G1CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); } // Initializes the underlying BitMap to cover the given area. void initialize(MemRegion heap, G1RegionToSpaceMapper* storage); @@ -146,9 +146,9 @@ class CMBitMap : public CMBitMapRO { }; // Represents a marking stack used by ConcurrentMarking in the G1 collector. -class CMMarkStack VALUE_OBJ_CLASS_SPEC { +class G1CMMarkStack VALUE_OBJ_CLASS_SPEC { VirtualSpace _virtual_space; // Underlying backing store for actual stack - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; oop* _base; // bottom of stack jint _index; // one more than last occupied index jint _capacity; // max #elements @@ -158,8 +158,8 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC { bool _should_expand; public: - CMMarkStack(ConcurrentMark* cm); - ~CMMarkStack(); + G1CMMarkStack(G1ConcurrentMark* cm); + ~G1CMMarkStack(); bool allocate(size_t capacity); @@ -220,19 +220,19 @@ class YoungList; // Currently, we only support root region scanning once (at the start // of the marking cycle) and the root regions are all the survivor // regions populated during the initial-mark pause. -class CMRootRegions VALUE_OBJ_CLASS_SPEC { +class G1CMRootRegions VALUE_OBJ_CLASS_SPEC { private: YoungList* _young_list; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; volatile bool _scan_in_progress; volatile bool _should_abort; HeapRegion* volatile _next_survivor; public: - CMRootRegions(); + G1CMRootRegions(); // We actually do most of the initialization in this method. - void init(G1CollectedHeap* g1h, ConcurrentMark* cm); + void init(G1CollectedHeap* g1h, G1ConcurrentMark* cm); // Reset the claiming / scanning of the root regions. void prepare_for_scan(); @@ -260,19 +260,19 @@ public: class ConcurrentMarkThread; -class ConcurrentMark: public CHeapObj { - friend class CMMarkStack; +class G1ConcurrentMark: public CHeapObj { friend class ConcurrentMarkThread; - friend class CMTask; - friend class CMBitMapClosure; - friend class CMRemarkTask; - friend class CMConcurrentMarkingTask; friend class G1ParNoteEndTask; friend class CalcLiveObjectsClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; friend class G1CMKeepAliveAndDrainClosure; friend class G1CMDrainMarkingStackClosure; + friend class G1CMBitMapClosure; + friend class G1CMConcurrentMarkingTask; + friend class G1CMMarkStack; + friend class G1CMRemarkTask; + friend class G1CMTask; protected: ConcurrentMarkThread* _cmThread; // The thread doing the work @@ -290,10 +290,10 @@ protected: FreeRegionList _cleanup_list; // Concurrent marking support structures - CMBitMap _markBitMap1; - CMBitMap _markBitMap2; - CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap - CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap + G1CMBitMap _markBitMap1; + G1CMBitMap _markBitMap2; + G1CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap + G1CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap BitMap _region_bm; BitMap _card_bm; @@ -303,10 +303,10 @@ protected: HeapWord* _heap_end; // Root region tracking and claiming - CMRootRegions _root_regions; + G1CMRootRegions _root_regions; // For gray objects - CMMarkStack _markStack; // Grey objects behind global finger + G1CMMarkStack _markStack; // Grey objects behind global finger HeapWord* volatile _finger; // The global finger, region aligned, // always points to the end of the // last claimed region @@ -314,8 +314,8 @@ protected: // Marking tasks uint _max_worker_id;// Maximum worker id uint _active_tasks; // Task num currently active - CMTask** _tasks; // Task queue array (max_worker_id len) - CMTaskQueueSet* _task_queues; // Task queue set + G1CMTask** _tasks; // Task queue array (max_worker_id len) + G1CMTaskQueueSet* _task_queues; // Task queue set ParallelTaskTerminator _terminator; // For termination // Two sync barriers that are used to synchronize tasks when an @@ -430,21 +430,21 @@ protected: bool out_of_regions() { return _finger >= _heap_end; } // Returns the task with the given id - CMTask* task(int id) { + G1CMTask* task(int id) { assert(0 <= id && id < (int) _active_tasks, "task id not within active bounds"); return _tasks[id]; } // Returns the task queue with the given id - CMTaskQueue* task_queue(int id) { + G1CMTaskQueue* task_queue(int id) { assert(0 <= id && id < (int) _active_tasks, "task queue id not within active bounds"); - return (CMTaskQueue*) _task_queues->queue(id); + return (G1CMTaskQueue*) _task_queues->queue(id); } // Returns the task queue set - CMTaskQueueSet* task_queues() { return _task_queues; } + G1CMTaskQueueSet* task_queues() { return _task_queues; } // Access / manipulation of the overflow flag which is set to // indicate that the global stack has overflown @@ -502,7 +502,7 @@ public: bool mark_stack_overflow() { return _markStack.overflow(); } bool mark_stack_empty() { return _markStack.isEmpty(); } - CMRootRegions* root_regions() { return &_root_regions; } + G1CMRootRegions* root_regions() { return &_root_regions; } bool concurrent_marking_in_progress() { return _concurrent_marking_in_progress; @@ -531,15 +531,15 @@ public: // Attempts to steal an object from the task queues of other tasks bool try_stealing(uint worker_id, int* hash_seed, oop& obj); - ConcurrentMark(G1CollectedHeap* g1h, - G1RegionToSpaceMapper* prev_bitmap_storage, - G1RegionToSpaceMapper* next_bitmap_storage); - ~ConcurrentMark(); + G1ConcurrentMark(G1CollectedHeap* g1h, + G1RegionToSpaceMapper* prev_bitmap_storage, + G1RegionToSpaceMapper* next_bitmap_storage); + ~G1ConcurrentMark(); ConcurrentMarkThread* cmThread() { return _cmThread; } - CMBitMapRO* prevMarkBitMap() const { return _prevMarkBitMap; } - CMBitMap* nextMarkBitMap() const { return _nextMarkBitMap; } + G1CMBitMapRO* prevMarkBitMap() const { return _prevMarkBitMap; } + G1CMBitMap* nextMarkBitMap() const { return _nextMarkBitMap; } // Returns the number of GC threads to be used in a concurrent // phase based on the number of GC threads being used in a STW @@ -728,7 +728,7 @@ protected: }; // A class representing a marking task. -class CMTask : public TerminatorTerminator { +class G1CMTask : public TerminatorTerminator { private: enum PrivateConstants { // the regular clock call is called once the scanned words reaches @@ -746,13 +746,13 @@ private: uint _worker_id; G1CollectedHeap* _g1h; - ConcurrentMark* _cm; - CMBitMap* _nextMarkBitMap; + G1ConcurrentMark* _cm; + G1CMBitMap* _nextMarkBitMap; // the task queue of this task - CMTaskQueue* _task_queue; + G1CMTaskQueue* _task_queue; private: // the task queue set---needed for stealing - CMTaskQueueSet* _task_queues; + G1CMTaskQueueSet* _task_queues; // indicates whether the task has been claimed---this is only for // debugging purposes bool _claimed; @@ -869,7 +869,7 @@ private: public: // It resets the task; it should be called right at the beginning of // a marking phase. - void reset(CMBitMap* _nextMarkBitMap); + void reset(G1CMBitMap* _nextMarkBitMap); // it clears all the fields that correspond to a claimed region. void clear_region_fields(); @@ -956,12 +956,12 @@ public: _finger = new_finger; } - CMTask(uint worker_id, - ConcurrentMark *cm, - size_t* marked_bytes, - BitMap* card_bm, - CMTaskQueue* task_queue, - CMTaskQueueSet* task_queues); + G1CMTask(uint worker_id, + G1ConcurrentMark *cm, + size_t* marked_bytes, + BitMap* card_bm, + G1CMTaskQueue* task_queue, + G1CMTaskQueueSet* task_queues); // it prints statistics associated with this task void print_stats(); @@ -1021,4 +1021,4 @@ public: ~G1PrintRegionLivenessInfoClosure(); }; -#endif // SHARE_VM_GC_G1_CONCURRENTMARK_HPP +#endif // SHARE_VM_GC_G1_G1CONCURRENTMARK_HPP diff --git a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp similarity index 83% rename from hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp rename to hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index d2695f59c70..4a934e0b15e 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -22,19 +22,19 @@ * */ -#ifndef SHARE_VM_GC_G1_CONCURRENTMARK_INLINE_HPP -#define SHARE_VM_GC_G1_CONCURRENTMARK_INLINE_HPP +#ifndef SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP +#define SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP -#include "gc/g1/concurrentMark.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1ConcurrentMark.hpp" #include "gc/shared/taskqueue.inline.hpp" // Utility routine to set an exclusive range of cards on the given // card liveness bitmap -inline void ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par) { +inline void G1ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, + BitMap::idx_t start_idx, + BitMap::idx_t end_idx, + bool is_par) { // Set the exclusive bit range [start_idx, end_idx). assert((end_idx - start_idx) > 0, "at least one card"); @@ -67,7 +67,7 @@ inline void ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, // Returns the index in the liveness accounting card bitmap // for the given address -inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { +inline BitMap::idx_t G1ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { // Below, the term "card num" means the result of shifting an address // by the card shift -- address 0 corresponds to card number 0. One // must subtract the card num of the bottom of the heap to obtain a @@ -78,9 +78,9 @@ inline BitMap::idx_t ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { // Counts the given memory region in the given task/worker // counting data structures. -inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { +inline void G1ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm) { G1CollectedHeap* g1h = _g1h; CardTableModRefBS* ct_bs = g1h->g1_barrier_set(); @@ -115,11 +115,11 @@ inline void ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, } // Counts the given object in the given task/worker counting data structures. -inline void ConcurrentMark::count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size) { +inline void G1ConcurrentMark::count_object(oop obj, + HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm, + size_t word_size) { assert(!hr->is_continues_humongous(), "Cannot enter count_object with continues humongous"); if (!hr->is_starts_humongous()) { MemRegion mr((HeapWord*)obj, word_size); @@ -135,10 +135,10 @@ inline void ConcurrentMark::count_object(oop obj, // Attempts to mark the given object and, if successful, counts // the object in the given task/worker counting structures. -inline bool ConcurrentMark::par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { +inline bool G1ConcurrentMark::par_mark_and_count(oop obj, + HeapRegion* hr, + size_t* marked_bytes_array, + BitMap* task_card_bm) { if (_nextMarkBitMap->parMark((HeapWord*)obj)) { // Update the task specific count data for the object. count_object(obj, hr, marked_bytes_array, task_card_bm, obj->size()); @@ -150,10 +150,10 @@ inline bool ConcurrentMark::par_mark_and_count(oop obj, // Attempts to mark the given object and, if successful, counts // the object in the task/worker counting structures for the // given worker id. -inline bool ConcurrentMark::par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id) { +inline bool G1ConcurrentMark::par_mark_and_count(oop obj, + size_t word_size, + HeapRegion* hr, + uint worker_id) { if (_nextMarkBitMap->parMark((HeapWord*)obj)) { size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); BitMap* task_card_bm = count_card_bitmap_for(worker_id); @@ -163,7 +163,7 @@ inline bool ConcurrentMark::par_mark_and_count(oop obj, return false; } -inline bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { +inline bool G1CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { HeapWord* start_addr = MAX2(startWord(), mr.start()); HeapWord* end_addr = MIN2(endWord(), mr.end()); @@ -186,7 +186,7 @@ inline bool CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { } // The argument addr should be the start address of a valid object -HeapWord* CMBitMapRO::nextObject(HeapWord* addr) { +HeapWord* G1CMBitMapRO::nextObject(HeapWord* addr) { oop obj = (oop) addr; HeapWord* res = addr + obj->size(); assert(offsetToHeapWord(heapWordToOffset(res)) == res, "sanity"); @@ -201,17 +201,17 @@ HeapWord* CMBitMapRO::nextObject(HeapWord* addr) { " corresponding to " PTR_FORMAT " (%u)", \ p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr)); -inline void CMBitMap::mark(HeapWord* addr) { +inline void G1CMBitMap::mark(HeapWord* addr) { check_mark(addr); _bm.set_bit(heapWordToOffset(addr)); } -inline void CMBitMap::clear(HeapWord* addr) { +inline void G1CMBitMap::clear(HeapWord* addr) { check_mark(addr); _bm.clear_bit(heapWordToOffset(addr)); } -inline bool CMBitMap::parMark(HeapWord* addr) { +inline bool G1CMBitMap::parMark(HeapWord* addr) { check_mark(addr); return _bm.par_set_bit(heapWordToOffset(addr)); } @@ -219,7 +219,7 @@ inline bool CMBitMap::parMark(HeapWord* addr) { #undef check_mark template -inline void CMMarkStack::iterate(Fn fn) { +inline void G1CMMarkStack::iterate(Fn fn) { assert(_saved_index == _index, "saved index: %d index: %d", _saved_index, _index); for (int i = 0; i < _index; ++i) { fn(_base[i]); @@ -227,9 +227,9 @@ inline void CMMarkStack::iterate(Fn fn) { } // It scans an object and visits its children. -inline void CMTask::scan_object(oop obj) { process_grey_object(obj); } +inline void G1CMTask::scan_object(oop obj) { process_grey_object(obj); } -inline void CMTask::push(oop obj) { +inline void G1CMTask::push(oop obj) { HeapWord* objAddr = (HeapWord*) obj; assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); assert(!_g1h->is_on_master_free_list( @@ -250,7 +250,7 @@ inline void CMTask::push(oop obj) { } } -inline bool CMTask::is_below_finger(oop obj, HeapWord* global_finger) const { +inline bool G1CMTask::is_below_finger(oop obj, HeapWord* global_finger) const { // If obj is above the global finger, then the mark bitmap scan // will find it later, and no push is needed. Similarly, if we have // a current region and obj is between the local finger and the @@ -281,7 +281,7 @@ inline bool CMTask::is_below_finger(oop obj, HeapWord* global_finger) const { } template -inline void CMTask::process_grey_object(oop obj) { +inline void G1CMTask::process_grey_object(oop obj) { assert(scan || obj->is_typeArray(), "Skipping scan of grey non-typeArray"); assert(_nextMarkBitMap->isMarked((HeapWord*) obj), "invariant"); @@ -296,10 +296,10 @@ inline void CMTask::process_grey_object(oop obj) { -inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) { +inline void G1CMTask::make_reference_grey(oop obj, HeapRegion* hr) { if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) { // No OrderAccess:store_load() is needed. It is implicit in the - // CAS done in CMBitMap::parMark() call in the routine above. + // CAS done in G1CMBitMap::parMark() call in the routine above. HeapWord* global_finger = _cm->finger(); // We only need to push a newly grey object on the mark @@ -335,7 +335,7 @@ inline void CMTask::make_reference_grey(oop obj, HeapRegion* hr) { } } -inline void CMTask::deal_with_reference(oop obj) { +inline void G1CMTask::deal_with_reference(oop obj) { increment_refs_reached(); HeapWord* objAddr = (HeapWord*) obj; @@ -354,14 +354,14 @@ inline void CMTask::deal_with_reference(oop obj) { } } -inline void ConcurrentMark::markPrev(oop p) { +inline void G1ConcurrentMark::markPrev(oop p) { assert(!_prevMarkBitMap->isMarked((HeapWord*) p), "sanity"); // Note we are overriding the read-only view of the prev map here, via // the cast. - ((CMBitMap*)_prevMarkBitMap)->mark((HeapWord*) p); + ((G1CMBitMap*)_prevMarkBitMap)->mark((HeapWord*) p); } -bool ConcurrentMark::isPrevMarked(oop p) const { +bool G1ConcurrentMark::isPrevMarked(oop p) const { assert(p != NULL && p->is_oop(), "expected an oop"); HeapWord* addr = (HeapWord*)p; assert(addr >= _prevMarkBitMap->startWord() || @@ -370,8 +370,8 @@ bool ConcurrentMark::isPrevMarked(oop p) const { return _prevMarkBitMap->isMarked(addr); } -inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, - uint worker_id, HeapRegion* hr) { +inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, + uint worker_id, HeapRegion* hr) { assert(obj != NULL, "pre-condition"); HeapWord* addr = (HeapWord*) obj; if (hr == NULL) { @@ -391,4 +391,4 @@ inline void ConcurrentMark::grayRoot(oop obj, size_t word_size, } } -#endif // SHARE_VM_GC_G1_CONCURRENTMARK_INLINE_HPP +#endif // SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp index d34f9d7501c..06721ee9295 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ */ #include "precompiled.hpp" -#include "gc/g1/concurrentMark.inline.hpp" #include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorState.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1EvacFailure.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" @@ -62,7 +62,7 @@ public: class RemoveSelfForwardPtrObjClosure: public ObjectClosure { private: G1CollectedHeap* _g1; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; HeapRegion* _hr; size_t _marked_bytes; OopsInHeapRegionClosure *_update_rset_cl; diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp index 1db22eb46a9..ca7643f59a8 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp index ce3c8308116..8b895582096 100644 --- a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp +++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp @@ -591,7 +591,7 @@ void G1HeapVerifier::verify_dirty_young_regions() { verify_dirty_young_list(_g1h->young_list()->first_region()); } -bool G1HeapVerifier::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, +bool G1HeapVerifier::verify_no_bits_over_tams(const char* bitmap_name, G1CMBitMapRO* bitmap, HeapWord* tams, HeapWord* end) { guarantee(tams <= end, "tams: " PTR_FORMAT " end: " PTR_FORMAT, p2i(tams), p2i(end)); @@ -605,8 +605,8 @@ bool G1HeapVerifier::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapR } bool G1HeapVerifier::verify_bitmaps(const char* caller, HeapRegion* hr) { - CMBitMapRO* prev_bitmap = _g1h->concurrent_mark()->prevMarkBitMap(); - CMBitMapRO* next_bitmap = (CMBitMapRO*) _g1h->concurrent_mark()->nextMarkBitMap(); + G1CMBitMapRO* prev_bitmap = _g1h->concurrent_mark()->prevMarkBitMap(); + G1CMBitMapRO* next_bitmap = (G1CMBitMapRO*) _g1h->concurrent_mark()->nextMarkBitMap(); HeapWord* bottom = hr->bottom(); HeapWord* ptams = hr->prev_top_at_mark_start(); diff --git a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp index c4fdb0d1057..4d6aa684093 100644 --- a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp +++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.hpp @@ -82,7 +82,7 @@ public: // range [from,limit). If it does, print an error message and return // false. Otherwise, just return true. bitmap_name should be "prev" // or "next". - bool verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, + bool verify_no_bits_over_tams(const char* bitmap_name, G1CMBitMapRO* bitmap, HeapWord* from, HeapWord* limit); // Verify that the prev / next bitmap range [tams,end) for the given diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp index d8c449fb603..05f90f75f4e 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp @@ -31,12 +31,12 @@ class HeapRegion; class G1CollectedHeap; class G1RemSet; -class ConcurrentMark; +class G1ConcurrentMark; class DirtyCardToOopClosure; -class CMBitMap; -class CMMarkStack; +class G1CMBitMap; +class G1CMMarkStack; class G1ParScanThreadState; -class CMTask; +class G1CMTask; class ReferenceProcessor; // A class that scans oops in a given heap region (much as OopsInGenClosure @@ -92,7 +92,7 @@ protected: G1ParScanThreadState* _par_scan_state; uint _worker_id; // Cache value from par_scan_state. Klass* _scanned_klass; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; // Mark the object if it's not already marked. This is used to mark // objects pointed to by roots that are guaranteed not to move @@ -170,12 +170,12 @@ public: // Closure for iterating over object fields during concurrent marking class G1CMOopClosure : public MetadataAwareOopClosure { protected: - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; private: G1CollectedHeap* _g1h; - CMTask* _task; + G1CMTask* _task; public: - G1CMOopClosure(G1CollectedHeap* g1h, ConcurrentMark* cm, CMTask* task); + G1CMOopClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, G1CMTask* task); template void do_oop_nv(T* p); virtual void do_oop( oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } @@ -185,10 +185,10 @@ public: class G1RootRegionScanClosure : public MetadataAwareOopClosure { private: G1CollectedHeap* _g1h; - ConcurrentMark* _cm; + G1ConcurrentMark* _cm; uint _worker_id; public: - G1RootRegionScanClosure(G1CollectedHeap* g1h, ConcurrentMark* cm, + G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, uint worker_id) : _g1h(g1h), _cm(cm), _worker_id(worker_id) { } template void do_oop_nv(T* p); diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index bdc18c62bcc..06289683254 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_GC_G1_G1OOPCLOSURES_INLINE_HPP #define SHARE_VM_GC_G1_G1OOPCLOSURES_INLINE_HPP -#include "gc/g1/concurrentMark.inline.hpp" #include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1RemSet.hpp" diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 52594f9f5a0..51750b8338e 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -51,9 +51,9 @@ #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS -#include "gc/g1/concurrentMark.hpp" #include "gc/g1/concurrentMarkThread.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/parallel/parallelScavengeHeap.inline.hpp" #include "gc/parallel/adjoiningGenerations.hpp" From 990924fe41c99eb4ef2b21a3094f90830e0b78b5 Mon Sep 17 00:00:00 2001 From: Alexander Kulyakhtin Date: Mon, 8 Feb 2016 14:50:54 +0300 Subject: [PATCH 064/139] 8147847: [TESTBUG] serviceability/tmtools/jstat test ported to JTREG are failing with -XX:+ExplicitGCInvokesConcurrent Fixed the test scenarios to eliminate false failures Reviewed-by: jbachorik --- .../test/serviceability/tmtools/jstat/GcCapacityTest.java | 4 ++-- .../test/serviceability/tmtools/jstat/GcCauseTest01.java | 4 ++-- hotspot/test/serviceability/tmtools/jstat/GcTest01.java | 4 ++-- .../serviceability/tmtools/jstat/utils/GcProvokerImpl.java | 4 ++-- .../tmtools/jstat/utils/JstatGcCapacityResults.java | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java index e695ca3d9bb..3b63e0210d1 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ import utils.*; * displayed with jstat -gccapacity. * @library /test/lib/share/classes * @library ../share - * @ignore 8147848 + * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @build common.* * @build utils.* * @run main/othervm -XX:+UsePerfData GcCapacityTest diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java index b233f770d61..55ee941e38c 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * collection time increase. * @library /test/lib/share/classes * @library ../share - * @ignore 8147848 + * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @build common.* * @build utils.* * diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java index 6b1c92bda8e..ee731adb144 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 +33,7 @@ * collection time increase. * @library /test/lib/share/classes * @library ../share - * @ignore 8147848 + * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @build common.* * @build utils.* * diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java index 309a5bd76db..388b53c5256 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ public class GcProvokerImpl implements GcProvoker { long edenSize = Pools.getEdenCommittedSize(); long heapSize = Pools.getHeapCommittedSize(); float targetPercent = ((float) edenSize) / (heapSize); - if ((targetPercent <= 0) || (targetPercent > 1.0)) { + if ((targetPercent < 0) || (targetPercent > 1.0)) { throw new RuntimeException("Error in the percent calculation" + " (eden size: " + edenSize + ", heap size: " + heapSize + ", calculated eden percent: " + targetPercent + ")"); } eatHeapMemory(targetPercent); diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java index c4eb9bdbda2..6ac62fa48ef 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,10 +77,10 @@ public class JstatGcCapacityResults extends JstatResults { assertThat(NGC <= NGCMX, "NGC > NGCMX (generation capacity > max generation capacity)"); float S0C = getFloatValue("S0C"); - assertThat(S0C < NGC, "S0C >= NGC (survivor space 0 capacity >= new generation capacity)"); + assertThat(S0C <= NGC, "S0C > NGC (survivor space 0 capacity > new generation capacity)"); float S1C = getFloatValue("S1C"); - assertThat(S1C < NGC, "S1C >= NGC (survivor space 1 capacity >= new generation capacity)"); + assertThat(S1C <= NGC, "S1C > NGC (survivor space 1 capacity > new generation capacity)"); float EC = getFloatValue("EC"); assertThat(EC <= NGC, "EC > NGC (eden space capacity > new generation capacity)"); From 3591c7bf383a86ed3c5edc417647d50d0117844d Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 8 Feb 2016 18:01:48 +0300 Subject: [PATCH 065/139] 8149364: Quarantine TestSelectDefaultGC.java test Reviewed-by: dfazunen, jwilhelm --- hotspot/test/gc/arguments/TestSelectDefaultGC.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/test/gc/arguments/TestSelectDefaultGC.java b/hotspot/test/gc/arguments/TestSelectDefaultGC.java index c3c043ce7e3..be8ffbcb304 100644 --- a/hotspot/test/gc/arguments/TestSelectDefaultGC.java +++ b/hotspot/test/gc/arguments/TestSelectDefaultGC.java @@ -29,6 +29,7 @@ * @library /testlibrary * @modules java.base/sun.misc * java.management + * @ignore 8148239 * @run driver TestSelectDefaultGC */ From a4844cbbc356d6a355bcf3190454c0b7b338bb9b Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Mon, 8 Feb 2016 18:54:09 +0300 Subject: [PATCH 066/139] 8148745: [testbug] Test gc/g1/plab/TestPLABPromotion.java fails in nightly Reviewed-by: tschatzl, dfazunen --- .../test/gc/g1/plab/TestPLABPromotion.java | 48 ++++++++++++++----- hotspot/test/gc/g1/plab/TestPLABResize.java | 1 + hotspot/test/gc/g1/plab/lib/PLABUtils.java | 1 + 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/hotspot/test/gc/g1/plab/TestPLABPromotion.java b/hotspot/test/gc/g1/plab/TestPLABPromotion.java index a2cddb8e768..54a56bb5092 100644 --- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java +++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java @@ -26,6 +26,7 @@ * @bug 8141278 * @summary Test PLAB promotion * @requires vm.gc=="G1" | vm.gc=="null" + * @requires vm.opt.FlightRecorder != true * @library /testlibrary /../../test/lib / * @modules java.management * @build ClassFileInstaller @@ -35,7 +36,7 @@ * gc.g1.plab.lib.AppPLABPromotion * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main gc.g1.plab.TestPLABPromotion + * @run main/timeout=240 gc.g1.plab.TestPLABPromotion */ package gc.g1.plab; @@ -62,9 +63,8 @@ public class TestPLABPromotion { // GC ID with old PLAB statistics private final static long GC_ID_OLD_STATS = 2l; - // Threshold to determine whether the correct amount of objects were promoted. - // This is only an approximate threshold for these checks. - private final static long MEM_CONSUMPTION_THRESHOLD = 256l * 1024l; + // Allowable difference for memory consumption (percentage) + private final static long MEM_DIFFERENCE_PCT = 5; private static final int PLAB_SIZE_SMALL = 1024; private static final int PLAB_SIZE_MEDIUM = 4096; @@ -147,11 +147,11 @@ public class TestPLABPromotion { // Unreachable objects case if (testCase.isDeadObjectCase()) { // No dead objects should be promoted - if (plabAllocatedSurvivor > MEM_CONSUMPTION_THRESHOLD || directAllocatedSurvivor > MEM_CONSUMPTION_THRESHOLD) { + if (!(checkRatio(plabAllocatedSurvivor, memAllocated) && checkRatio(directAllocatedSurvivor, memAllocated))) { System.out.println(output); throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Survivor"); } - if (plabAllocatedOld > MEM_CONSUMPTION_THRESHOLD || directAllocatedOld > MEM_CONSUMPTION_THRESHOLD) { + if (!(checkRatio(plabAllocatedOld, memAllocated) && checkRatio(directAllocatedOld, memAllocated))) { System.out.println(output); throw new RuntimeException("Unreachable objects should not be allocated using PLAB or direct allocated to Old"); } @@ -159,32 +159,32 @@ public class TestPLABPromotion { // Live objects case if (testCase.isPromotedByPLAB()) { // All live small objects should be promoted using PLAB - if (Math.abs(plabAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + if (!checkDifferenceRatio(plabAllocatedSurvivor, memAllocated)) { System.out.println(output); throw new RuntimeException("Expect that Survivor PLAB allocation are similar to all mem consumed"); } - if (Math.abs(plabAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + if (!checkDifferenceRatio(plabAllocatedOld, memAllocated)) { System.out.println(output); throw new RuntimeException("Expect that Old PLAB allocation are similar to all mem consumed"); } } else { // All big objects should be directly allocated - if (Math.abs(directAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + if (!checkDifferenceRatio(directAllocatedSurvivor, memAllocated)) { System.out.println(output); throw new RuntimeException("Test fails. Expect that Survivor direct allocation are similar to all mem consumed"); } - if (Math.abs(directAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + if (!checkDifferenceRatio(directAllocatedOld, memAllocated)) { System.out.println(output); throw new RuntimeException("Test fails. Expect that Old direct allocation are similar to all mem consumed"); } } // All promoted objects size should be similar to all consumed memory - if (Math.abs(plabAllocatedSurvivor + directAllocatedSurvivor - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + if (!checkDifferenceRatio(plabAllocatedSurvivor + directAllocatedSurvivor, memAllocated)) { System.out.println(output); throw new RuntimeException("Test fails. Expect that Survivor gen total allocation are similar to all mem consumed"); } - if (Math.abs(plabAllocatedOld + directAllocatedOld - memAllocated) > MEM_CONSUMPTION_THRESHOLD) { + if (!checkDifferenceRatio(plabAllocatedOld + directAllocatedOld, memAllocated)) { System.out.println(output); throw new RuntimeException("Test fails. Expect that Old gen total allocation are similar to all mem consumed"); } @@ -192,6 +192,30 @@ public class TestPLABPromotion { System.out.println("Test passed!"); } + /** + * Returns true if checkedValue is less than MEM_DIFFERENCE_PCT percent of controlValue. + * + * @param checkedValue - checked value + * @param controlValue - referent value + * @return true if checkedValue is less than MEM_DIFFERENCE_PCT percent of controlValue + */ + private static boolean checkRatio(long checkedValue, long controlValue) { + return (Math.abs(checkedValue) / controlValue) * 100L < MEM_DIFFERENCE_PCT; + } + + /** + * Returns true if difference of checkedValue and controlValue is less than + * MEM_DIFFERENCE_PCT percent of controlValue. + * + * @param checkedValue - checked value + * @param controlValue - referent value + * @return true if difference of checkedValue and controlValue is less than + * MEM_DIFFERENCE_PCT percent of controlValue + */ + private static boolean checkDifferenceRatio(long checkedValue, long controlValue) { + return (Math.abs(checkedValue - controlValue) / controlValue) * 100L < MEM_DIFFERENCE_PCT; + } + private static Map getPlabStats(LogParser logParser, LogParser.ReportType type, long gc_id) { Map survivorStats = logParser.getEntries() diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java index 18aef6a949b..07a05ce90c3 100644 --- a/hotspot/test/gc/g1/plab/TestPLABResize.java +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java @@ -26,6 +26,7 @@ * @bug 8141278 * @summary Test for PLAB resizing * @requires vm.gc=="G1" | vm.gc=="null" + * @requires vm.opt.FlightRecorder != true * @library /testlibrary /../../test/lib / * @modules java.management * @build ClassFileInstaller diff --git a/hotspot/test/gc/g1/plab/lib/PLABUtils.java b/hotspot/test/gc/g1/plab/lib/PLABUtils.java index 3c61f6b28fb..ee13f0a2fa2 100644 --- a/hotspot/test/gc/g1/plab/lib/PLABUtils.java +++ b/hotspot/test/gc/g1/plab/lib/PLABUtils.java @@ -41,6 +41,7 @@ public class PLABUtils { "-XX:G1HeapRegionSize=1m", "-XX:OldSize=64m", "-XX:-UseAdaptiveSizePolicy", + "-XX:MaxTenuringThreshold=1", "-XX:-UseTLAB", "-XX:SurvivorRatio=1" }; From be21417b0623f36ee033f95e344848b79944cf34 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Thu, 17 Dec 2015 16:12:58 +0300 Subject: [PATCH 067/139] 8144695: --disable-warnings-as-errors does not work for HotSpot build Reviewed-by: kbarrett, ihse --- hotspot/make/bsd/makefiles/gcc.make | 2 +- hotspot/make/linux/makefiles/gcc.make | 2 +- hotspot/make/solaris/makefiles/adlc.make | 10 +++++++--- hotspot/make/solaris/makefiles/gcc.make | 2 +- hotspot/make/solaris/makefiles/sparcWorks.make | 3 ++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index fc7b25fceaa..05a07052963 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -256,7 +256,7 @@ endif # Compiler warnings are treated as errors ifneq ($(COMPILER_WARNINGS_FATAL),false) - WARNINGS_ARE_ERRORS = -Werror + WARNINGS_ARE_ERRORS ?= -Werror endif ifeq ($(USE_CLANG), true) diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index 835ad2fda3a..c8ee95d932b 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -203,7 +203,7 @@ else endif # Compiler warnings are treated as errors -WARNINGS_ARE_ERRORS = -Werror +WARNINGS_ARE_ERRORS ?= -Werror ifeq ($(USE_CLANG), true) # However we need to clean the code up before we can unrestrictedly enable this option with Clang diff --git a/hotspot/make/solaris/makefiles/adlc.make b/hotspot/make/solaris/makefiles/adlc.make index 77d6692b903..730a5a36eca 100644 --- a/hotspot/make/solaris/makefiles/adlc.make +++ b/hotspot/make/solaris/makefiles/adlc.make @@ -66,17 +66,21 @@ CXXFLAGS = $(SYSDEFS) $(INCLUDES) CXXFLAGS += -DASSERT ifndef USE_GCC - # We need libCstd.so for adlc + # We need libCstd.so for adlc CFLAGS += -library=Cstd -g LFLAGS += -library=Cstd -g endif # CFLAGS_WARN holds compiler options to suppress/enable warnings. +CFLAGS_WARN = +w # Compiler warnings are treated as errors ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) - CFLAGS_WARN = +w -errwarn + WARNINGS_ARE_ERRORS ?= -xwe endif -# When using compiler version 5.13 (Solaris Studio 12.4), calls to explicitly + +CFLAGS_WARN += $(WARNINGS_ARE_ERRORS) + +# When using compiler version 5.13 (Solaris Studio 12.4), calls to explicitly # instantiated template functions trigger this warning when +w is active. ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 513), 1) CFLAGS_WARN += -erroff=notemsource diff --git a/hotspot/make/solaris/makefiles/gcc.make b/hotspot/make/solaris/makefiles/gcc.make index dc78122ae84..d31237acbf1 100644 --- a/hotspot/make/solaris/makefiles/gcc.make +++ b/hotspot/make/solaris/makefiles/gcc.make @@ -117,7 +117,7 @@ endif # Compiler warnings are treated as errors -WARNINGS_ARE_ERRORS = -Werror +WARNINGS_ARE_ERRORS ?= -Werror # Enable these warnings. See 'info gcc' about details on these options WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef -Wformat=2 diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make index 9bdab00ba66..cbd902ef0fe 100644 --- a/hotspot/make/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -145,7 +145,8 @@ endif CFLAGS += -DDONT_USE_PRECOMPILED_HEADER # Compiler warnings are treated as errors -CFLAGS_WARN = -xwe +WARNINGS_ARE_ERRORS ?= -xwe +CFLAGS_WARN = $(WARNINGS_ARE_ERRORS) ################################################ # Begin current (>=5.9) Forte compiler options # From 10b052918809bbcba05a1ff0b91db5edf850d6af Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 19 Feb 2016 07:55:05 +0000 Subject: [PATCH 068/139] 8150168: jconsole AboutDialog should use the JDK specific Version API Reviewed-by: alanb, iris --- .../share/classes/sun/tools/jconsole/AboutDialog.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/AboutDialog.java b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/AboutDialog.java index 8f198bf6c24..8e54a707142 100644 --- a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/AboutDialog.java +++ b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/AboutDialog.java @@ -34,8 +34,6 @@ import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; -import static sun.misc.Version.jdkMinorVersion; - import static java.awt.BorderLayout.*; import static sun.tools.jconsole.Utilities.*; @@ -183,7 +181,7 @@ public class AboutDialog extends InternalDialog { } private static String getOnlineDocUrl() { - String version = Integer.toString(jdkMinorVersion()); + String version = Integer.toString(jdk.Version.current().major()); return Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL, version); } From a9a633b1acfb7cbb7d996e594c6877e599c46ebf Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 19 Feb 2016 07:56:25 +0000 Subject: [PATCH 069/139] 8150163: JarFileSystem support for MRJARs should use the JDK specific Version API Reviewed-by: alanb, iris, sherman --- .../classes/jdk/nio/zipfs/JarFileSystem.java | 7 ++--- .../jdk/nio/zipfs/MultiReleaseJarTest.java | 27 ++++++++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java index ec874229fdc..36650dcbf94 100644 --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java @@ -36,6 +36,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.jar.Attributes; import java.util.jar.Manifest; +import jdk.Version; /** * Adds aliasing to ZipFileSystem to support multi-release jar files. An alias map @@ -68,14 +69,14 @@ class JarFileSystem extends ZipFileSystem { if (o instanceof String) { String s = (String)o; if (s.equals("runtime")) { - version = sun.misc.Version.jdkMajorVersion(); // fixme waiting for jdk.util.Version + version = jdk.Version.current().major(); } else { version = Integer.parseInt(s); } } else if (o instanceof Integer) { version = (Integer)o; - } else if (false /*o instanceof Version*/) { // fixme waiting for jdk.util.Version -// version = ((Version)o).major(); + } else if (o instanceof Version) { + version = ((Version)o).major(); } else { throw new IllegalArgumentException("env parameter must be String, Integer, " + "or Version"); diff --git a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java index 09d1c335d70..f409e2b4cd5 100644 --- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java +++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java @@ -38,16 +38,18 @@ import java.net.URI; import java.nio.file.*; import java.util.HashMap; import java.util.Map; - -import static sun.misc.Version.jdkMajorVersion; +import jdk.Version; import org.testng.Assert; import org.testng.annotations.*; public class MultiReleaseJarTest { + final private int MAJOR_VERSION= Version.current().major(); + final private String userdir = System.getProperty("user.dir","."); final private Map stringEnv = new HashMap<>(); final private Map integerEnv = new HashMap<>(); + final private Map versionEnv = new HashMap<>(); final private String className = "version.Version"; final private MethodType mt = MethodType.methodType(int.class); @@ -81,7 +83,7 @@ public class MultiReleaseJarTest { @DataProvider(name="strings") public Object[][] createStrings() { return new Object[][]{ - {"runtime", jdkMajorVersion()}, + {"runtime", MAJOR_VERSION}, {"-20", 8}, {"0", 8}, {"8", 8}, @@ -105,6 +107,17 @@ public class MultiReleaseJarTest { }; } + @DataProvider(name="versions") + public Object[][] createVersions() { + return new Object[][] { + {Version.parse("8"), 8}, + {Version.parse("9"), 9}, + {Version.parse("10"), 10}, + {Version.parse("11"), 10}, + {Version.parse("100"), 10} + }; + } + // Not the best test but all I can do since ZipFileSystem and JarFileSystem // are not public, so I can't use (fs instanceof ...) @Test @@ -117,7 +130,7 @@ public class MultiReleaseJarTest { env.put("multi-release", "runtime"); // a configuration and jar file is multi-release try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) { - Assert.assertTrue(readAndCompare(fs, jdkMajorVersion())); + Assert.assertTrue(readAndCompare(fs, MAJOR_VERSION)); } // a configuration but jar file is unversioned try (FileSystem fs = FileSystems.newFileSystem(uvuri, env)) { @@ -143,6 +156,12 @@ public class MultiReleaseJarTest { runTest(integerEnv, expected); } + @Test(dataProvider="versions") + public void testVersions(Version value, int expected) throws Throwable { + versionEnv.put("multi-release", value); + runTest(versionEnv, expected); + } + @Test public void testShortJar() throws Throwable { integerEnv.put("multi-release", Integer.valueOf(10)); From ee5b32591130f560b90ec2cea7ab40d0612ecb8d Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 28 Dec 2015 12:16:09 +0100 Subject: [PATCH 070/139] 8145919: sun/management/jmxremote/bootstrap/RmiSslBootstrapTest failed with Connection failed for no credentials Reviewed-by: dfuchs --- jdk/test/ProblemList.txt | 3 --- .../management_ssltest07_ok.properties.in | 4 ++-- .../jmxremote/bootstrap/ssl/Readme.txt | 11 +++++++++++ .../jmxremote/bootstrap/ssl/keystore | Bin 1364 -> 1295 bytes .../jmxremote/bootstrap/ssl/truststore | Bin 661 -> 888 bytes 5 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 jdk/test/sun/management/jmxremote/bootstrap/ssl/Readme.txt diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index ece21ff2b50..5b07bb2d65f 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -165,9 +165,6 @@ javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java generi # 8147985 sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java generic-all -# 8145919 -sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh generic-all - ############################################################################ # jdk_net diff --git a/jdk/test/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in b/jdk/test/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in index 036d3f3c19e..21fa833234c 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in +++ b/jdk/test/sun/management/jmxremote/bootstrap/management_ssltest07_ok.properties.in @@ -1,5 +1,5 @@ -com.sun.management.jmxremote.ssl.enabled.cipher.suites=SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5 +com.sun.management.jmxremote.ssl.enabled.cipher.suites=TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 com.sun.management.jmxremote.ssl.enabled.protocols=SSLv2Hello,SSLv3,TLSv1 com.sun.management.jmxremote.ssl.need.client.auth=true com.sun.management.jmxremote.authenticate=false -javax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5 +javax.rmi.ssl.client.enabledCipherSuites=TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 diff --git a/jdk/test/sun/management/jmxremote/bootstrap/ssl/Readme.txt b/jdk/test/sun/management/jmxremote/bootstrap/ssl/Readme.txt new file mode 100644 index 00000000000..48b5478ab32 --- /dev/null +++ b/jdk/test/sun/management/jmxremote/bootstrap/ssl/Readme.txt @@ -0,0 +1,11 @@ +The trustore and keystore are to be generated as follows: + +1. keytool -genkey -alias duke -keystore keystore -validity 36500 +- use password 'password' for the keystore and key passwords +- leave all values at default +- the certificate validity will be 100 years (should be enough for now) +2. keytool -export -keystore keystore -alias duke -file duke.crt +3. keytool -import -keystore truststore -alias duke -file duke.crt +- use password 'trustword' for the keystore and key passwords +- leave all values at default + diff --git a/jdk/test/sun/management/jmxremote/bootstrap/ssl/keystore b/jdk/test/sun/management/jmxremote/bootstrap/ssl/keystore index 05f535645827bae28d6168fe4ad38f55b4faa076..f756c3b0ef182eb5aed6151343b2d8bac2f998d9 100644 GIT binary patch literal 1295 zcmezO_TO6u1_mY|W&~rFl+x@}ASdW^SI1f)-EYvu*loba#-+{1$ik?_B*@6f%D~dZ zST1SaefrLKws)>pO3#k2_3yfJ>CfrCo_kxXCdZ}-Wbvv#caFX@M}R?T3sdvMjTinV zZAf^1gkNp(`7fI%*WbF^CimoI#<3Pf%_*gOw5FU|^YKYhvCTs9L|Iu`ec7g8^>6yN zJa~|87xZRA&BAK=H`7l>`fXfwx0prP{-MbK-#kiTXub!lSlhAjoI>gH2!S%KkrUHA4hl~cPg)Ps_5a%^CGcYo=Ft9K&G%|~l;5RY^3K$xhLIvpTo+ic}!1SvF3lK&i zN1my%k>PKBaHDLgkY><*uQ_^eo;?31xIM_`y$i!(Is1lffohqqu?|XszawpXBYy2a z`gNDVx6`vjbFMd9H^`dge@aW(o;@>Q>5}>LU$9gQC>`?Oz4H3M?Z>2lScgA9wqltm zKg;jtZss$WDKSgVz39PsoJo{ndO|?Is51ANO_O#u zEqdL;{UJi;E68czA1-LUHrw{z={>7s%yxwDtemob_b;ngO+UkZxNX^+(gP#I`*vN4 z^nX^!F3{Mp#Z#$nDF-VoJKt-mOZo)tLhG^>D73!c%7W~=4GW5^A^{0|57wf z`uIDkic!V-%#x4$Rs>GyT+w|0Vbs(4Y?Hdv;u@+$RZ|#!tpA<&)M9RIWdH|Juz1&c zNu3vL|F8O8HBy{!)O6=t=G9ug+@sI;w0i&dS+%JDHU~dvx6$l-Qn6l9FB==%wk})d z++piJX=7kKbBj3hJ&}kfn?kr5>QCHP`+oSIw({D#HpOlGOb@b`D=bah>Lwt6Zja2z zFURg}n6pZ%tk>UY@;1i(!dK@7#(aI@@_DhMfxLk%Fy+efv52vV)R;wjFWO-8f`7}c z-y%m-i|=-6=%A!@W_<<&9VU@*nN$37;$qr@hkF12KHL<$XP4X`CK2J+MQpQH<$gFh lJ$%w^FR!$V({?Rw-)Z6-#F`Ux>qt}Kw0oNNlUm=_0s!xn2I>F+ literal 1364 zcmezO_TO6u1_mY|W&~rFl+x@}AnVJnxrbPQ61xqWn6?}6v2kg$F|sgfF$pp@x>ho1^r&%56_HAo+kX-fS_qrLG%Yn5yK^;n~6$t&>v*xw~)X3eP!zSgL%KOtM?csA62-VTT4$i1_bl&AJ8J4Kf~ ziYq>~>~z7T=JwQ&`THIyDly((cmBuZsJWL9R9dwM*e?9V^W<2oX~rE?2@~@Z_DXF{XSl#`RkR;Szp|kbZYS*iaruy^P zST}Z@wO{qwyZOTFL-+qoSh8dGH)oMlb>{<@F6u5daCMvdGfKYnm+_yf)kmFuzP$0; zUO$K9wCIbL!f!l{|DreY@0nkf-PE&2@iS+ksfS&YmU@(7le43t zh=CADhFzFDI5DpzQNcMUu_)0{-ar;4$|WooT$-ogo0(jcUtC#SlA2qrqu`mBtY^q; zzztHsEzII&6zmG)G7Gb~0P~oEoH(z6v4M$^v7xbnk%2*!IIppRfu(^3luLgHHO@y4 z6JR!HZtP_+XzXNaY-HGfCcO30-Nk>C&t^D3kre0H7s|HG%zJ|HgZJC_FP+00a)3{8 z>dl}fM{>-U?K)u?^slWj`}isG>HM2}Hf@xwP3+FPCH2Eu?D39r?N9aJ&br)Lbi`95G5&Q? z%Y`i+Gi`!B4lzGva^Ygy+7q!NgeN#ov?O}MlGRgNvaYtgc(UBxPV3kQ^@DF}rhYtg zZtpz@_BOUjDzmggY+H9)n(a*vTbg~J;Y+sM;`SA@pBVj}AqIW@RwQF%&T1V`C0wVH0K#&CAZqFVBOCaA1hAV~B8Jh;U0UCfdYm`rcePoyQhh9hd~pg4lFfTc_3&ws&EEueJBfA`Ak|F$2K{$U;d{Md?RqWmnso4;K? zDtDO4G(Z%Pl04DZ`@CDQ*{A-h0h z!xm4mLgg1e8e+oR&vP2}oLKhIMy#qkq^4Kn!Qypt+MAb^PRv_e&;3i$H0k5-q$)-g z>oZF}?pqN!p>sv^{fALc=d(@fPK#@(4pmKI^s)YT-cyUYv6TTFM8V=+>m_wwu>HU4 zchyL7zERViZ<$wX^>U9s-_z>--)GgL{@WbkQnRAD&`=pJ5 z@yspa%=bhho@@%?W~e`LU+w$hd)mrt>)I5z?K3^dUaqh-ZL6Dr{JA|cAHN*Cw_(mI zsj^;wqsiMC_X}U07Z~&Ph0Eu~iU#rqvcQxp%f}+dB2r@(>Ah%!$qW81w|T9y0Z7FE^hfT8wL5MaTbaqqEPJ*6Pa%Kx``rL*VMa6n literal 661 zcmezO_TO6u1_mY|W(3n5DW%z|$*DypK;D;K^M2+sutw;a8dw6=gcvk21sF6j?qp)I zTh@2NfR~L^tIebBJ1-+63oC;`z9F{(CmVAp3!5-gXfTY!A|Xg7Aa)+xIV>!y0mcPjKqZpe09g%$Myt zVHovdhjZj%K8IQPahLD-cyDL3^t-z{g1PXojrhM3%^3}^cKpjWE!;bG@5VE8^P1m# zwVl1{7ZbDj&;h%LjZ8wTCJ4`e`e`SF!W;o6r?AX#*@B;xnV1w2n|n5Gl&nqc&blS_!&&U{j&ki!_216A+*x$QQzJ3{by3TOEgds$f;|o~ zKV@>^V%pjhu_A;gI8L-Adcu;`Q(LmGw!C<<+}%#=*a!84Z)&D~JacaEJqPwSwn-|p zv_foKcUqe5O%7X{eV^e=w%p?O6| Date: Thu, 4 Feb 2016 12:33:31 +0100 Subject: [PATCH 071/139] 8143897: Weblogic12medrec assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true)) failed: Must be the same ExceptionCache read is lock-free and assume strong memory ordering in write code. Added storestore memory barrier in write path to handle this. Reviewed-by: kvn, thartmann, dlong --- hotspot/src/share/vm/code/nmethod.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 7dc841279c6..600dfde31e4 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -321,9 +321,12 @@ address ExceptionCache::test_address(address addr) { bool ExceptionCache::add_address_and_handler(address addr, address handler) { if (test_address(addr) == handler) return true; - if (count() < cache_size) { - set_pc_at(count(),addr); - set_handler_at(count(), handler); + + int index = count(); + if (index < cache_size) { + set_pc_at(index, addr); + set_handler_at(index, handler); + OrderAccess::storestore(); increment_count(); return true; } From 76b459d629d53069cc6863ea562f64cf2508d50e Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Wed, 3 Feb 2016 12:16:44 +0100 Subject: [PATCH 072/139] 8146608: [JVMCI] DebugInfo Tests on DeoptimizeALot runs fails in assert(_pc == *pc_addr || pc == *pc_addr) frame::patch_pc() /frame_x86.cpp:285 Reviewed-by: twisti --- .../vm/ci/hotspot/HotSpotCompiledCode.java | 9 ++-- .../vm/ci/hotspot/HotSpotCompiledNmethod.java | 5 ++- .../src/share/vm/jvmci/jvmciCodeInstaller.cpp | 19 +++++++- .../src/share/vm/jvmci/jvmciCodeInstaller.hpp | 2 +- .../src/share/vm/jvmci/jvmciJavaClasses.hpp | 2 +- .../compiler/jvmci/code/TestAssembler.java | 8 +++- .../jvmci/code/amd64/AMD64TestAssembler.java | 1 + .../jvmci/code/sparc/SPARCTestAssembler.java | 1 + .../jvmci/errors/CodeInstallerTest.java | 5 ++- .../errors/TestInvalidCompilationResult.java | 44 +++++++++++-------- .../jvmci/errors/TestInvalidDebugInfo.java | 11 ++++- .../jvmci/errors/TestInvalidOopMap.java | 3 +- .../events/JvmciNotifyInstallEventTest.java | 2 +- 13 files changed, 78 insertions(+), 34 deletions(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java index 5605cdb429d..48d861515ab 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java @@ -24,6 +24,7 @@ package jdk.vm.ci.hotspot; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.CompiledCode; +import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.DataPatch; import jdk.vm.ci.code.site.Infopoint; import jdk.vm.ci.code.site.Site; @@ -99,9 +100,9 @@ public class HotSpotCompiledCode implements CompiledCode { protected final int totalFrameSize; /** - * Offset in bytes for the custom stack area (relative to sp). + * The deopt rescue slot. Must be non-null if there is a safepoint in the method. */ - protected final int customStackAreaOffset; + protected final StackSlot deoptRescueSlot; public static class Comment { @@ -115,7 +116,7 @@ public class HotSpotCompiledCode implements CompiledCode { } public HotSpotCompiledCode(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection, - int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, int customStackAreaOffset) { + int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot) { this.name = name; this.targetCode = targetCode; this.targetCodeSize = targetCodeSize; @@ -129,7 +130,7 @@ public class HotSpotCompiledCode implements CompiledCode { this.dataSectionPatches = dataSectionPatches; this.isImmutablePIC = isImmutablePIC; this.totalFrameSize = totalFrameSize; - this.customStackAreaOffset = customStackAreaOffset; + this.deoptRescueSlot = deoptRescueSlot; assert validateFrames(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java index a2038a57341..4255a5f41f3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java @@ -22,6 +22,7 @@ */ package jdk.vm.ci.hotspot; +import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.DataPatch; import jdk.vm.ci.code.site.Site; import jdk.vm.ci.inittimer.SuppressFBWarnings; @@ -55,9 +56,9 @@ public final class HotSpotCompiledNmethod extends HotSpotCompiledCode { @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "set by the VM") private String installationFailureMessage; public HotSpotCompiledNmethod(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection, - int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, int customStackAreaOffset, HotSpotResolvedJavaMethod method, int entryBCI, + int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot, HotSpotResolvedJavaMethod method, int entryBCI, int id, long jvmciEnv, boolean hasUnsafeAccess) { - super(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, totalFrameSize, customStackAreaOffset); + super(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, totalFrameSize, deoptRescueSlot); this.method = method; this.entryBCI = entryBCI; this.id = id; diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index bd56e38c08e..492fd538421 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -546,7 +546,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand // Make sure a valid compile_id is associated with every compile id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci); } - result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, + result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, compiler, _debug_recorder, _dependencies, env, id, has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log); @@ -576,7 +576,19 @@ void CodeInstaller::initialize_fields(oop target, oop compiled_code, TRAPS) { _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code)); _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code); _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code); - _custom_stack_area_offset = HotSpotCompiledCode::customStackAreaOffset(compiled_code); + + oop deoptRescueSlot = HotSpotCompiledCode::deoptRescueSlot(compiled_code); + if (deoptRescueSlot == NULL) { + _orig_pc_offset = -1; + } else { + _orig_pc_offset = StackSlot::offset(deoptRescueSlot); + if (StackSlot::addFrameSize(deoptRescueSlot)) { + _orig_pc_offset += _total_frame_size; + } + if (_orig_pc_offset < 0) { + JVMCI_ERROR("invalid deopt rescue slot: %d", _orig_pc_offset); + } + } // Pre-calculate the constants section size. This is required for PC-relative addressing. _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code)); @@ -724,6 +736,9 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, if (site_InfopointReason::SAFEPOINT() == reason || site_InfopointReason::CALL() == reason || site_InfopointReason::IMPLICIT_EXCEPTION() == reason) { TRACE_jvmci_4("safepoint at %i", pc_offset); site_Safepoint(buffer, pc_offset, site, CHECK_OK); + if (_orig_pc_offset < 0) { + JVMCI_ERROR_OK("method contains safepoint, but has not deopt rescue slot"); + } } else { TRACE_jvmci_4("infopoint at %i", pc_offset); site_Infopoint(buffer, pc_offset, site, CHECK_OK); diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp index ccf6a6d836f..4c682489b32 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp @@ -125,7 +125,7 @@ private: jobject _code_handle; jint _code_size; jint _total_frame_size; - jint _custom_stack_area_offset; + jint _orig_pc_offset; jint _parameter_count; jint _constants_size; #ifndef PRODUCT diff --git a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp index 083f726d170..e9fd2b29929 100644 --- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp @@ -91,7 +91,7 @@ class JVMCIJavaClasses : AllStatic { objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Ljdk/vm/ci/code/site/DataPatch;") \ boolean_field(HotSpotCompiledCode, isImmutablePIC) \ int_field(HotSpotCompiledCode, totalFrameSize) \ - int_field(HotSpotCompiledCode, customStackAreaOffset) \ + oop_field(HotSpotCompiledCode, deoptRescueSlot, "Ljdk/vm/ci/code/StackSlot;") \ end_class \ start_class(HotSpotCompiledCode_Comment) \ oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;") \ diff --git a/hotspot/test/compiler/jvmci/code/TestAssembler.java b/hotspot/test/compiler/jvmci/code/TestAssembler.java index 4ed5b938dcd..d9a15ac2dc5 100644 --- a/hotspot/test/compiler/jvmci/code/TestAssembler.java +++ b/hotspot/test/compiler/jvmci/code/TestAssembler.java @@ -181,6 +181,8 @@ public abstract class TestAssembler { private int stackAlignment; private int curStackSlot; + private StackSlot deoptRescue; + protected TestAssembler(CodeCacheProvider codeCache, int initialFrameSize, int stackAlignment, PlatformKind narrowOopKind, Register... registers) { this.narrowOopKind = LIRKind.reference(narrowOopKind); @@ -216,6 +218,10 @@ public abstract class TestAssembler { return StackSlot.get(kind, -curStackSlot, true); } + protected void setDeoptRescueSlot(StackSlot deoptRescue) { + this.deoptRescue = deoptRescue; + } + protected void recordImplicitException(DebugInfo info) { sites.add(new Infopoint(code.position(), info, InfopointReason.IMPLICIT_EXCEPTION)); } @@ -249,7 +255,7 @@ public abstract class TestAssembler { byte[] finishedData = data.finish(); DataPatch[] finishedDataPatches = dataPatches.toArray(new DataPatch[0]); return new HotSpotCompiledNmethod(method.getName(), finishedCode, finishedCode.length, finishedSites, new Assumption[0], new ResolvedJavaMethod[]{method}, new Comment[0], finishedData, 16, - finishedDataPatches, false, frameSize, 0, method, 0, id, 0L, false); + finishedDataPatches, false, frameSize, deoptRescue, method, 0, id, 0L, false); } protected static class Buffer { diff --git a/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java b/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java index c67192674a2..80bf2d17fd1 100644 --- a/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java +++ b/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java @@ -63,6 +63,7 @@ public class AMD64TestAssembler extends TestAssembler { emitFatNop(); code.emitByte(0x50 | AMD64.rbp.encoding); // PUSH rbp emitMove(true, AMD64.rbp, AMD64.rsp); // MOV rbp, rsp + setDeoptRescueSlot(newStackSlot(LIRKind.value(AMD64Kind.QWORD))); } @Override diff --git a/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java b/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java index 7b423641e18..d0bcc9c013c 100644 --- a/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java +++ b/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java @@ -68,6 +68,7 @@ public class SPARCTestAssembler extends TestAssembler { @Override public void emitPrologue() { emitOp3(0b10, SPARC.sp, 0b111100, SPARC.sp, -SPARC.REGISTER_SAFE_AREA_SIZE); // SAVE sp, -128, sp + setDeoptRescueSlot(newStackSlot(LIRKind.value(SPARCKind.XWORD))); } @Override diff --git a/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java b/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java index b06697634b2..2d7617d778a 100644 --- a/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java +++ b/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java @@ -28,6 +28,7 @@ import java.lang.reflect.Method; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.DataPatch; import jdk.vm.ci.code.site.Site; import jdk.vm.ci.hotspot.HotSpotCompiledCode; @@ -71,9 +72,9 @@ public class CodeInstallerTest { dummyMethod = metaAccess.lookupJavaMethod(method); } - protected void installEmptyCode(Site[] sites, Assumption[] assumptions, Comment[] comments, int dataSectionAlignment, DataPatch[] dataSectionPatches) { + protected void installEmptyCode(Site[] sites, Assumption[] assumptions, Comment[] comments, int dataSectionAlignment, DataPatch[] dataSectionPatches, StackSlot deoptRescueSlot) { HotSpotCompiledCode code = new HotSpotCompiledCode("dummyMethod", new byte[0], 0, sites, assumptions, new ResolvedJavaMethod[]{dummyMethod}, comments, new byte[8], dataSectionAlignment, - dataSectionPatches, false, 0, 0); + dataSectionPatches, false, 0, deoptRescueSlot); codeCache.addCode(dummyMethod, code, null, null); } diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java index 928bd74522e..90284c115de 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java @@ -30,6 +30,7 @@ package compiler.jvmci.errors; +import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.ConstantReference; import jdk.vm.ci.code.site.DataPatch; import jdk.vm.ci.code.site.DataSectionReference; @@ -80,104 +81,111 @@ public class TestInvalidCompilationResult extends CodeInstallerTest { @Test(expected = JVMCIError.class) public void testInvalidAssumption() { - installEmptyCode(new Site[0], new Assumption[]{new InvalidAssumption()}, new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[0], new Assumption[]{new InvalidAssumption()}, new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testInvalidAlignment() { - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 7, new DataPatch[0]); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 7, new DataPatch[0], null); } @Test(expected = NullPointerException.class) public void testNullDataPatchInDataSection() { - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{null}); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{null}, null); } @Test(expected = NullPointerException.class) public void testNullReferenceInDataSection() { - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, null)}); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, null)}, null); } @Test(expected = JVMCIError.class) public void testInvalidDataSectionReference() { DataSectionReference ref = new DataSectionReference(); ref.setOffset(0); - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}, null); } @Test(expected = JVMCIError.class) public void testInvalidNarrowMethodInDataSection() { HotSpotConstant c = (HotSpotConstant) dummyMethod.getEncoding(); ConstantReference ref = new ConstantReference((VMConstant) c.compress()); - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}, null); } @Test(expected = NullPointerException.class) public void testNullConstantInDataSection() { ConstantReference ref = new ConstantReference(null); - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}, null); } @Test(expected = JVMCIError.class) public void testInvalidConstantInDataSection() { ConstantReference ref = new ConstantReference(new InvalidVMConstant()); - installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}); + installEmptyCode(new Site[0], new Assumption[0], new Comment[0], 16, new DataPatch[]{new DataPatch(0, ref)}, null); } @Test(expected = NullPointerException.class) public void testNullReferenceInCode() { - installEmptyCode(new Site[]{new DataPatch(0, null)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new DataPatch(0, null)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = NullPointerException.class) public void testNullConstantInCode() { ConstantReference ref = new ConstantReference(null); - installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testInvalidConstantInCode() { ConstantReference ref = new ConstantReference(new InvalidVMConstant()); - installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testInvalidReference() { InvalidReference ref = new InvalidReference(); - installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testOutOfBoundsDataSectionReference() { DataSectionReference ref = new DataSectionReference(); ref.setOffset(0x1000); - installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new DataPatch(0, ref)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testInvalidMark() { - installEmptyCode(new Site[]{new Mark(0, new Object())}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new Mark(0, new Object())}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testInvalidMarkInt() { - installEmptyCode(new Site[]{new Mark(0, -1)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new Mark(0, -1)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = NullPointerException.class) public void testNullSite() { - installEmptyCode(new Site[]{null}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{null}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testInfopointMissingDebugInfo() { Infopoint info = new Infopoint(0, null, InfopointReason.METHOD_START); - installEmptyCode(new Site[]{info}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{info}, new Assumption[0], new Comment[0], 16, new DataPatch[0], null); } @Test(expected = JVMCIError.class) public void testSafepointMissingDebugInfo() { Infopoint info = new Infopoint(0, null, InfopointReason.SAFEPOINT); - installEmptyCode(new Site[]{info}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + StackSlot deoptRescueSlot = StackSlot.get(null, 0, true); + installEmptyCode(new Site[]{info}, new Assumption[0], new Comment[0], 16, new DataPatch[0], deoptRescueSlot); + } + + @Test(expected = JVMCIError.class) + public void testInvalidDeoptRescueSlot() { + StackSlot deoptRescueSlot = StackSlot.get(null, -1, false); + installEmptyCode(new Site[]{}, new Assumption[0], new Comment[0], 16, new DataPatch[0], deoptRescueSlot); } } diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java index e95d5cea6dc..6ca22fa9cab 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java @@ -66,10 +66,14 @@ public class TestInvalidDebugInfo extends CodeInstallerTest { } private void test(VirtualObject[] vobj, JavaValue[] values, JavaKind[] slotKinds, int locals, int stack, int locks) { + test(vobj, values, slotKinds, locals, stack, locks, StackSlot.get(null, 0, true)); + } + + private void test(VirtualObject[] vobj, JavaValue[] values, JavaKind[] slotKinds, int locals, int stack, int locks, StackSlot deoptRescueSlot) { BytecodeFrame frame = new BytecodeFrame(null, dummyMethod, 0, false, false, values, slotKinds, locals, stack, locks); DebugInfo info = new DebugInfo(frame, vobj); info.setReferenceMap(new HotSpotReferenceMap(new Location[0], new Location[0], new int[0], 8)); - installEmptyCode(new Site[]{new Infopoint(0, info, InfopointReason.SAFEPOINT)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new Infopoint(0, info, InfopointReason.SAFEPOINT)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], deoptRescueSlot); } @Test(expected = NullPointerException.class) @@ -82,6 +86,11 @@ public class TestInvalidDebugInfo extends CodeInstallerTest { test(new JavaValue[0], null, 0, 0, 0); } + @Test(expected = JVMCIError.class) + public void testMissingDeoptRescueSlot() { + test(null, new JavaValue[0], new JavaKind[0], 0, 0, 0, null); + } + @Test(expected = JVMCIError.class) public void testUnexpectedScopeValuesLength() { test(new JavaValue[]{JavaConstant.FALSE}, new JavaKind[0], 0, 0, 0); diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java index f5efaf91375..0f1fe6e873c 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java @@ -35,6 +35,7 @@ import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.Location; import jdk.vm.ci.code.ReferenceMap; import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.DataPatch; import jdk.vm.ci.code.site.Infopoint; import jdk.vm.ci.code.site.InfopointReason; @@ -61,7 +62,7 @@ public class TestInvalidOopMap extends CodeInstallerTest { BytecodePosition pos = new BytecodePosition(null, dummyMethod, 0); DebugInfo info = new DebugInfo(pos); info.setReferenceMap(refMap); - installEmptyCode(new Site[]{new Infopoint(0, info, InfopointReason.SAFEPOINT)}, new Assumption[0], new Comment[0], 16, new DataPatch[0]); + installEmptyCode(new Site[]{new Infopoint(0, info, InfopointReason.SAFEPOINT)}, new Assumption[0], new Comment[0], 16, new DataPatch[0], StackSlot.get(null, 0, true)); } @Test(expected = NullPointerException.class) diff --git a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java index 2b9d8c9332e..75c808e34cc 100644 --- a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java +++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java @@ -109,7 +109,7 @@ public class JvmciNotifyInstallEventTest implements HotSpotVMEventListener { .getResolvedMethod(SimpleClass.class, testMethod); HotSpotCompiledCode compiledCode = new HotSpotCompiledCode(METHOD_NAME, new byte[0], 0, new Site[0], new Assumption[0], new ResolvedJavaMethod[]{method}, new Comment[0], new byte[0], 16, - new DataPatch[0], false, 0, 0); + new DataPatch[0], false, 0, null); codeCache.installCode(method, compiledCode, /* installedCode = */ null, /* speculationLog = */ null, /* isDefault = */ false); Asserts.assertEQ(gotInstallNotification, 1, From 56c2dccccf8b9ff8deec5eed6ef6bc539849cca5 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 3 Feb 2016 12:16:44 +0100 Subject: [PATCH 073/139] 8148981: remove ResolvedJavaType.getClassFilePath() Reviewed-by: twisti --- .../hotspot/HotSpotResolvedObjectTypeImpl.java | 8 -------- .../hotspot/HotSpotResolvedPrimitiveType.java | 6 ------ .../src/jdk/vm/ci/meta/ResolvedJavaType.java | 6 ------ .../ci/runtime/test/TestResolvedJavaType.java | 18 ------------------ 4 files changed, 38 deletions(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index a87e540f7a1..3b1dc5abf9f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -33,7 +33,6 @@ import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; @@ -49,7 +48,6 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ModifiersProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -838,12 +836,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem return null; } - @Override - public URL getClassFilePath() { - Class cls = mirror(); - return cls.getResource(MetaUtil.getSimpleName(cls, true).replace('.', '$') + ".class"); - } - @Override public boolean isLocal() { return mirror().isLocalClass(); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index b8039190175..06e03ae69f2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -27,7 +27,6 @@ import static java.util.Objects.requireNonNull; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Modifier; -import java.net.URL; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.Assumptions.AssumptionResult; @@ -239,11 +238,6 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType return kind.toJavaClass(); } - @Override - public URL getClassFilePath() { - return null; - } - @Override public boolean isLocal() { return false; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java index 3649c267f6b..3be863e751e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java @@ -23,7 +23,6 @@ package jdk.vm.ci.meta; import java.lang.annotation.Annotation; -import java.net.URL; import jdk.vm.ci.meta.Assumptions.AssumptionResult; @@ -307,11 +306,6 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider { */ String getSourceFileName(); - /** - * Returns the class file path - if available - of this type, or {@code null}. - */ - URL getClassFilePath(); - /** * Returns {@code true} if the type is a local type. */ diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 37b430ff908..3fa46c10196 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -47,7 +47,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.net.URL; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -849,23 +848,6 @@ public class TestResolvedJavaType extends TypeUniverse { } } - @Test - public void classFilePathTest() { - for (Class c : classes) { - ResolvedJavaType type = metaAccess.lookupJavaType(c); - URL path = type.getClassFilePath(); - if (type.isPrimitive() || type.isArray()) { - assertEquals(null, path); - } else { - assertNotNull(path); - String pathString = path.getPath(); - if (type.isLocal() || type.isMember()) { - assertTrue(pathString.indexOf('$') > 0); - } - } - } - } - @Test public void isTrustedInterfaceTypeTest() { for (Class c : classes) { From ae0867c9f8ad589c7d4971b472b6143e1497fad4 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Fri, 22 Jan 2016 15:25:40 +0100 Subject: [PATCH 074/139] 8063112: Compiler diagnostic commands should have locking instead of safepoint Remove unnecessary vm-ops and add locking instead, improve output Reviewed-by: kvn --- hotspot/src/share/vm/code/codeCache.cpp | 5 ++- .../src/share/vm/compiler/compileBroker.cpp | 21 ++++++------ .../src/share/vm/compiler/compileBroker.hpp | 2 -- hotspot/src/share/vm/runtime/thread.cpp | 32 ++++++++++++++++- hotspot/src/share/vm/runtime/thread.hpp | 2 ++ .../src/share/vm/runtime/vm_operations.cpp | 12 ------- .../src/share/vm/runtime/vm_operations.hpp | 34 ------------------- .../share/vm/services/diagnosticCommand.cpp | 9 ++--- 8 files changed, 48 insertions(+), 69 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 314365dda91..c7c31c30d3b 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -1494,7 +1494,7 @@ void CodeCache::print_summary(outputStream* st, bool detailed) { } void CodeCache::print_codelist(outputStream* st) { - assert_locked_or_safepoint(CodeCache_lock); + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); NMethodIterator iter; while(iter.next_alive()) { @@ -1508,9 +1508,8 @@ void CodeCache::print_codelist(outputStream* st) { } void CodeCache::print_layout(outputStream* st) { - assert_locked_or_safepoint(CodeCache_lock); + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); ResourceMark rm; - print_summary(st, true); } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 497c0568754..7f9868986af 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -466,9 +466,16 @@ CompileQueue* CompileBroker::compile_queue(int comp_level) { return NULL; } - void CompileBroker::print_compile_queues(outputStream* st) { + st->print_cr("Current compiles: "); MutexLocker locker(MethodCompileQueue_lock); + MutexLocker locker2(Threads_lock); + + char buf[2000]; + int buflen = sizeof(buf); + Threads::print_threads_compiling(st, buf, buflen); + + st->cr(); if (_c1_compile_queue != NULL) { _c1_compile_queue->print(st); } @@ -479,8 +486,7 @@ void CompileBroker::print_compile_queues(outputStream* st) { void CompileQueue::print(outputStream* st) { assert(MethodCompileQueue_lock->owned_by_self(), "must own lock"); - st->print_cr("Contents of %s", name()); - st->print_cr("----------------------------"); + st->print_cr("%s:", name()); CompileTask* task = _first; if (task == NULL) { st->print_cr("Empty"); @@ -490,7 +496,7 @@ void CompileQueue::print(outputStream* st) { task = task->next(); } } - st->print_cr("----------------------------"); + st->cr(); } void CompileQueue::print_tty() { @@ -2355,10 +2361,3 @@ void CompileBroker::print_last_compile() { } } - -void CompileBroker::print_compiler_threads_on(outputStream* st) { -#ifndef PRODUCT - st->print_cr("Compiler thread printing unimplemented."); - st->cr(); -#endif -} diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index d74646b8855..92169d035a4 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -350,8 +350,6 @@ public: // Debugging output for failure static void print_last_compile(); - static void print_compiler_threads_on(outputStream* st); - // compiler name for debugging static const char* compiler_name(int comp_level); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 70e3ec6c8c4..b0fca00705a 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -31,6 +31,7 @@ #include "code/codeCacheExtensions.hpp" #include "code/scopeDesc.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/compileTask.hpp" #include "gc/shared/gcId.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "gc/shared/workgroup.hpp" @@ -2884,6 +2885,20 @@ void JavaThread::print_on(outputStream *st) const { print_thread_state_on(st); _safepoint_state->print_on(st); #endif // PRODUCT + if (is_Compiler_thread()) { + CompilerThread* ct = (CompilerThread*)this; + if (ct->task() != NULL) { + st->print(" Compiling: "); + ct->task()->print(st, NULL, true, false); + } else { + st->print(" No compile task"); + } + st->cr(); + } +} + +void JavaThread::print_name_on_error(outputStream* st, char *buf, int buflen) const { + st->print("%s", get_thread_name_string(buf, buflen)); } // Called by fatal error handler. The difference between this and @@ -4386,7 +4401,6 @@ void Threads::print_on(outputStream* st, bool print_stacks, wt->print_on(st); st->cr(); } - CompileBroker::print_compiler_threads_on(st); st->flush(); } @@ -4439,8 +4453,24 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, current->print_on_error(st, buf, buflen); st->cr(); } + st->cr(); + st->print_cr("Threads with active compile tasks:"); + print_threads_compiling(st, buf, buflen); } +void Threads::print_threads_compiling(outputStream* st, char* buf, int buflen) { + ALL_JAVA_THREADS(thread) { + if (thread->is_Compiler_thread()) { + CompilerThread* ct = (CompilerThread*) thread; + if (ct->task() != NULL) { + thread->print_name_on_error(st, buf, buflen); + ct->task()->print(st, NULL, true, true); + } + } + } +} + + // Internal SpinLock and Mutex // Based on ParkEvent diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 79d7c04568f..4d94026e313 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1660,6 +1660,7 @@ class JavaThread: public Thread { void print_thread_state_on(outputStream*) const PRODUCT_RETURN; void print_thread_state() const PRODUCT_RETURN; void print_on_error(outputStream* st, char* buf, int buflen) const; + void print_name_on_error(outputStream* st, char* buf, int buflen) const; void verify(); const char* get_thread_name() const; private: @@ -2158,6 +2159,7 @@ class Threads: AllStatic { print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */); } static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen); + static void print_threads_compiling(outputStream* st, char* buf, int buflen); // Get Java threads that are waiting to enter a monitor. If doLock // is true, then Threads_lock is grabbed as needed. Otherwise, the diff --git a/hotspot/src/share/vm/runtime/vm_operations.cpp b/hotspot/src/share/vm/runtime/vm_operations.cpp index 7e5d06c0162..80def983a56 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.cpp +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp @@ -485,18 +485,6 @@ void VM_Exit::wait_if_vm_exited() { } } -void VM_PrintCompileQueue::doit() { - CompileBroker::print_compile_queues(_out); -} - -void VM_PrintCodeList::doit() { - CodeCache::print_codelist(_out); -} - -void VM_PrintCodeCache::doit() { - CodeCache::print_layout(_out); -} - #if INCLUDE_SERVICES void VM_PrintClassHierarchy::doit() { KlassHierarchy::print_class_hierarchy(_out, _print_interfaces, _print_subclasses, _classname); diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 061c8b4c205..03392091aee 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -105,9 +105,6 @@ template(DumpHashtable) \ template(DumpTouchedMethods) \ template(MarkActiveNMethods) \ - template(PrintCompileQueue) \ - template(PrintCodeList) \ - template(PrintCodeCache) \ template(PrintClassHierarchy) \ class VM_Operation: public CHeapObj { @@ -424,37 +421,6 @@ class VM_Exit: public VM_Operation { void doit(); }; -class VM_PrintCompileQueue: public VM_Operation { - private: - outputStream* _out; - - public: - VM_PrintCompileQueue(outputStream* st) : _out(st) {} - VMOp_Type type() const { return VMOp_PrintCompileQueue; } - Mode evaluation_mode() const { return _no_safepoint; } - void doit(); -}; - -class VM_PrintCodeList: public VM_Operation { - private: - outputStream* _out; - - public: - VM_PrintCodeList(outputStream* st) : _out(st) {} - VMOp_Type type() const { return VMOp_PrintCodeList; } - void doit(); -}; - -class VM_PrintCodeCache: public VM_Operation { - private: - outputStream* _out; - - public: - VM_PrintCodeCache(outputStream* st) : _out(st) {} - VMOp_Type type() const { return VMOp_PrintCodeCache; } - void doit(); -}; - #if INCLUDE_SERVICES class VM_PrintClassHierarchy: public VM_Operation { private: diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index bad2098eb17..d6dde5eef83 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -832,18 +832,15 @@ void VMDynamicLibrariesDCmd::execute(DCmdSource source, TRAPS) { } void CompileQueueDCmd::execute(DCmdSource source, TRAPS) { - VM_PrintCompileQueue printCompileQueueOp(output()); - VMThread::execute(&printCompileQueueOp); + CompileBroker::print_compile_queues(output()); } void CodeListDCmd::execute(DCmdSource source, TRAPS) { - VM_PrintCodeList printCodeListOp(output()); - VMThread::execute(&printCodeListOp); + CodeCache::print_codelist(output()); } void CodeCacheDCmd::execute(DCmdSource source, TRAPS) { - VM_PrintCodeCache printCodeCacheOp(output()); - VMThread::execute(&printCodeCacheOp); + CodeCache::print_layout(output()); } void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) { From 7e9c407a86b7356c08ca964be7ee9ad4ddea4a64 Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Fri, 5 Feb 2016 11:33:27 +0100 Subject: [PATCH 075/139] 8149105: typo in jvmciCodeInstaller.cpp Reviewed-by: twisti --- hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index 492fd538421..87f239a7dc0 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -737,7 +737,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, TRACE_jvmci_4("safepoint at %i", pc_offset); site_Safepoint(buffer, pc_offset, site, CHECK_OK); if (_orig_pc_offset < 0) { - JVMCI_ERROR_OK("method contains safepoint, but has not deopt rescue slot"); + JVMCI_ERROR_OK("method contains safepoint, but has no deopt rescue slot"); } } else { TRACE_jvmci_4("infopoint at %i", pc_offset); From 2bdb607d7d4b029bf6b5667bdfab4ee3d3f3f068 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 5 Feb 2016 12:43:57 +0100 Subject: [PATCH 076/139] 8149109: [TESTBUG] TestRegisterRestoring.java fails with "VM option 'SafepointALot' is develop" Added missing -XX:+IgnoreUnrecognizedVMOptions. Reviewed-by: vlivanov --- .../test/compiler/runtime/safepoints/TestRegisterRestoring.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/test/compiler/runtime/safepoints/TestRegisterRestoring.java b/hotspot/test/compiler/runtime/safepoints/TestRegisterRestoring.java index 6742d7fb99c..08c2cb75a86 100644 --- a/hotspot/test/compiler/runtime/safepoints/TestRegisterRestoring.java +++ b/hotspot/test/compiler/runtime/safepoints/TestRegisterRestoring.java @@ -27,7 +27,7 @@ * @test * @bug 8148490 * @summary Test correct saving and restoring of vector registers at safepoints. - * @run main/othervm -Xbatch -XX:-TieredCompilation -XX:CompileCommand=exclude,TestRegisterRestoring::main -XX:+SafepointALot TestRegisterRestoring + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:-TieredCompilation -XX:CompileCommand=exclude,TestRegisterRestoring::main -XX:+SafepointALot TestRegisterRestoring */ public class TestRegisterRestoring { public static void main(String args[]) throws Exception { From fc58d951d28c1a8d542f7be8f09d9b187e0b42f2 Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Fri, 5 Feb 2016 18:05:33 +0300 Subject: [PATCH 077/139] 8148864: Quarantine CompilerControl tests Exclude tests affected by JDK-8148563 and JDK-8140354 from execution Reviewed-by: kvn --- hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java | 1 + hotspot/test/compiler/compilercontrol/commands/PrintTest.java | 1 + hotspot/test/compiler/compilercontrol/directives/PrintTest.java | 1 + .../test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java | 1 + .../compilercontrol/jcmd/StressAddMultiThreadedTest.java | 1 + .../compiler/compilercontrol/mixed/RandomValidCommandsTest.java | 1 + 6 files changed, 6 insertions(+) diff --git a/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java index c3fab210fac..ede2eb65776 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java @@ -26,6 +26,7 @@ * @bug 8137167 * @summary Tests CompileCommand=print * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @ignore 8140354 * @build compiler.compilercontrol.commandfile.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* diff --git a/hotspot/test/compiler/compilercontrol/commands/PrintTest.java b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java index 758b733e06a..eddeadbfbe7 100644 --- a/hotspot/test/compiler/compilercontrol/commands/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java @@ -26,6 +26,7 @@ * @bug 8137167 * @summary Tests CompileCommand=print * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @ignore 8140354 * @build compiler.compilercontrol.commands.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* diff --git a/hotspot/test/compiler/compilercontrol/directives/PrintTest.java b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java index a0e8dc071f8..78ac4de4cee 100644 --- a/hotspot/test/compiler/compilercontrol/directives/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java @@ -26,6 +26,7 @@ * @bug 8137167 * @summary Tests directives to be able to turn on print_assembly * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @ignore 8140354 * @build compiler.compilercontrol.directives.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* diff --git a/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java index 632e79e6c22..5821de76d75 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java @@ -26,6 +26,7 @@ * @bug 8137167 * @summary Tests jcmd to be able to add a directive to compile only specified methods * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @ignore 8140354 * @build compiler.compilercontrol.jcmd.PrintDirectivesTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java index 326a8a0b4b6..b2ad879351a 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java @@ -27,6 +27,7 @@ * @summary Tests jcmd to be able to add a lot of huge directive files with * parallel executed jcmds until timeout has reached * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @ignore 8148563 * @build compiler.compilercontrol.jcmd.StressAddMultiThreadedTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils diff --git a/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java index 4d93e7dd3e1..7b837e672c5 100644 --- a/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java @@ -26,6 +26,7 @@ * @bug 8137167 * @summary Randomly generates valid commands with random types * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @ignore 8140354 * @build compiler.compilercontrol.mixed.RandomValidCommandsTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* From 25db23a65e75260b4bccea6b48aa04134092effa Mon Sep 17 00:00:00 2001 From: Tatiana Pivovarova Date: Fri, 5 Feb 2016 21:16:14 +0300 Subject: [PATCH 078/139] 8149135: [jittester] Makefile copies JitTesterDriver in incorrect directory and always uses default value for number-of-tests and seed Reviewed-by: iignatyev --- hotspot/test/testlibrary/jittester/Makefile | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hotspot/test/testlibrary/jittester/Makefile b/hotspot/test/testlibrary/jittester/Makefile index 53f62ba99c6..c4ccd025049 100644 --- a/hotspot/test/testlibrary/jittester/Makefile +++ b/hotspot/test/testlibrary/jittester/Makefile @@ -35,6 +35,15 @@ ifeq "x$(TESTBASE_DIR)" "x" TESTBASE_DIR := ws/hotspot/test endif +APPLICATION_ARGS = +ifneq "x$(TESTS_NUMBER)" "x" + APPLICATION_ARGS += --number-of-tests $(TESTS_NUMBER) +endif + +ifneq "x$(SEED)" "x" + APPLICATION_ARGS += --seed $(SEED) +endif + JAVA = $(JDK_HOME)/bin/java JAVAC = $(JDK_HOME)/bin/javac JAR = $(JDK_HOME)/bin/jar @@ -43,8 +52,9 @@ BUILD_DIR = build CLASSES_DIR = $(BUILD_DIR)/classes SRC_DIR = src TEST_DIR = test +DRIVER_DIR = $(TESTBASE_DIR)/jdk/test/lib/jittester/jtreg MANIFEST = manifest.mf -APPLICATION_ARGS = \ +APPLICATION_ARGS += \ --property-file $(PROPERTY_FILE) \ --testbase-dir $(TESTBASE_DIR) MAIN_CLASS = JitTestGenerator.Automatic @@ -103,8 +113,8 @@ cleantmp: @rm filelist @rm -rf $(CLASSES_DIR) -copytestlibrary: - @cp -r src/jdk/test/lib/jittester/jtreg $(TESTBASE_DIR)/ +copytestlibrary: $(DRIVER_DIR) + @cp -r src/jdk/test/lib/jittester/jtreg/*.java $(DRIVER_DIR) @cp -r ../jdk $(TESTBASE_DIR)/ testgroup: $(TESTBASE_DIR) @@ -117,9 +127,6 @@ testgroup: $(TESTBASE_DIR) testroot: $(TESTBASE_DIR) @echo 'groups=TEST.groups' > $(TESTROOT_FILE) -$(TESTBASE_DIR): - $(shell if [ ! -d $@ ]; then mkdir -p $@; fi) - -$(DIST_DIR): +$(TESTBASE_DIR) $(DIST_DIR) $(DRIVER_DIR): $(shell if [ ! -d $@ ]; then mkdir -p $@; fi) From 938471481bcb5fa548b342cd3f9122c9d56e7e7d Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 5 Feb 2016 12:27:02 -0800 Subject: [PATCH 079/139] 8149076: [JVMCI] missing ResourceMark in JVMCIRuntime::initialize_HotSpotJVMCIRuntime Reviewed-by: twisti, iignatyev --- hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 1 + .../jvmci/JVM_GetJVMCIRuntimeTest.java | 55 +++++++++---------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index ec205b11ce4..716f73c06b1 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -634,6 +634,7 @@ Handle JVMCIRuntime::callStatic(const char* className, const char* methodName, c void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { if (JNIHandles::resolve(_HotSpotJVMCIRuntime_instance) == NULL) { + ResourceMark rm; #ifdef ASSERT // This should only be called in the context of the JVMCI class being initialized TempNewSymbol name = SymbolTable::new_symbol("jdk/vm/ci/runtime/JVMCI", CHECK); diff --git a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java index 0d7960ee55a..30bcd1e63b4 100644 --- a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java +++ b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java @@ -35,6 +35,16 @@ * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=false * -XX:-EnableJVMCI * compiler.jvmci.JVM_GetJVMCIRuntimeTest + * @run main/othervm -XX:+UnlockExperimentalVMOptions + * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true + * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.threaded=true + * -XX:+EnableJVMCI + * compiler.jvmci.JVM_GetJVMCIRuntimeTest + * @run main/othervm -XX:+UnlockExperimentalVMOptions + * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=false + * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.threaded=true + * -XX:-EnableJVMCI + * compiler.jvmci.JVM_GetJVMCIRuntimeTest */ @@ -43,22 +53,27 @@ package compiler.jvmci; import jdk.vm.ci.runtime.JVMCI; import jdk.test.lib.Asserts; -import java.lang.reflect.Method; - -public class JVM_GetJVMCIRuntimeTest { +public class JVM_GetJVMCIRuntimeTest implements Runnable { private static final boolean IS_POSITIVE = Boolean.getBoolean( "compiler.jvmci.JVM_GetJVMCIRuntimeTest.positive"); + private static final boolean IN_THREAD = Boolean.getBoolean( + "compiler.jvmci.JVM_GetJVMCIRuntimeTest.threaded"); - private final Method initializeRuntime; - - public static void main(String[] args) { - new JVM_GetJVMCIRuntimeTest().runTest(); + public static void main(String[] args) throws Throwable { + JVM_GetJVMCIRuntimeTest instance = new JVM_GetJVMCIRuntimeTest(); + if (IN_THREAD) { + Thread t = new Thread(instance); + t.start(); + t.join(); + } else { + instance.run(); + } } - private void runTest() { + public void run() { Object result; try { - result = invoke(); + result = JVMCI.getRuntime(); } catch (InternalError e) { if (IS_POSITIVE) { throw new AssertionError("unexpected exception", e); @@ -70,28 +85,8 @@ public class JVM_GetJVMCIRuntimeTest { } Asserts.assertNotNull(result, "initializeRuntime returned null"); - Asserts.assertEQ(result, invoke(), + Asserts.assertEQ(result, JVMCI.getRuntime(), "initializeRuntime returns different results"); } - private Object invoke() { - Object result; - try { - result = initializeRuntime.invoke(JVMCI.class); - } catch (ReflectiveOperationException e) { - throw new Error("can't invoke initializeRuntime", e); - } - return result; - } - - private JVM_GetJVMCIRuntimeTest() { - Method method; - try { - method = JVMCI.class.getDeclaredMethod("initializeRuntime"); - method.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new Error("can't find JVMCI::initializeRuntime", e); - } - initializeRuntime = method; - } } From eab1474601355fa8b326d71da4eca407ee206a00 Mon Sep 17 00:00:00 2001 From: Zoltan Majo Date: Mon, 8 Feb 2016 08:57:39 +0100 Subject: [PATCH 080/139] 8148758: Compilation fails with "this call site should not be polymorphic" Change test to run in interpreter-only mode. Reviewed-by: kvn --- .../test/testlibrary_tests/whitebox/vm_flags/IntxTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java index 2ce4c17ec15..b12f3065b22 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java @@ -23,14 +23,13 @@ /* * @test IntxTest - * @bug 8028756 - * @ignore 8148758 + * @bug 8038756 * @library /testlibrary /test/lib * @modules java.management/sun.management * @build IntxTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-ProfileInterpreter IntxTest + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint -XX:-ProfileInterpreter IntxTest * @summary testing of WB::set/getIntxVMFlag() * @author igor.ignatyev@oracle.com */ From 044e5ececc79b987faba39e03654ddb96f857789 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Mon, 8 Feb 2016 14:05:45 +0100 Subject: [PATCH 081/139] 8148696: Race loading hsdis may cause SIGSEGV Guard library loading with a lock Reviewed-by: vlivanov --- hotspot/src/share/vm/compiler/disassembler.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/compiler/disassembler.hpp b/hotspot/src/share/vm/compiler/disassembler.hpp index fb718b2b026..eca47a798f8 100644 --- a/hotspot/src/share/vm/compiler/disassembler.hpp +++ b/hotspot/src/share/vm/compiler/disassembler.hpp @@ -85,6 +85,7 @@ class Disassembler { public: static bool can_decode() { + ttyLocker tl; return (_decode_instructions_virtual != NULL) || (_decode_instructions != NULL) || load_library(); From 60a582e9beb28a2286b030631da27b4fb5c32545 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 8 Feb 2016 18:52:03 +0100 Subject: [PATCH 082/139] 8149019: remove redundant modifiers Reviewed-by: twisti --- hotspot/.mx.jvmci/suite.py | 2 +- .../src/jdk/vm/ci/aarch64/AArch64.java | 16 ++++++------- .../src/jdk/vm/ci/aarch64/AArch64Kind.java | 4 ++-- .../src/jdk/vm/ci/amd64/AMD64.java | 4 ++-- .../src/jdk/vm/ci/amd64/AMD64Kind.java | 4 ++-- .../src/jdk/vm/ci/code/SourceStackTrace.java | 4 ++-- .../hotspot/HotSpotCallingConventionType.java | 2 +- .../vm/ci/hotspot/HotSpotConstantPool.java | 4 ++-- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 4 +++- .../HotSpotMemoryAccessProviderImpl.java | 2 +- .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 24 +++++++++---------- .../ci/hotspot/HotSpotMethodDataAccessor.java | 2 +- .../ci/hotspot/HotSpotMethodUnresolved.java | 2 +- .../hotspot/HotSpotResolvedJavaFieldImpl.java | 2 +- .../HotSpotResolvedObjectTypeImpl.java | 2 +- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 12 +++++----- .../jdk/vm/ci/meta/DeoptimizationAction.java | 2 +- .../src/jdk/vm/ci/meta/JavaKind.java | 2 +- .../src/jdk/vm/ci/meta/LIRKind.java | 2 +- .../ci/meta/MethodHandleAccessProvider.java | 2 +- .../src/jdk/vm/ci/meta/PlatformKind.java | 2 +- .../src/jdk/vm/ci/sparc/SPARCKind.java | 4 ++-- .../vm/ci/runtime/test/NameAndSignature.java | 2 +- .../ci/runtime/test/TestResolvedJavaType.java | 2 +- 24 files changed, 55 insertions(+), 53 deletions(-) diff --git a/hotspot/.mx.jvmci/suite.py b/hotspot/.mx.jvmci/suite.py index 28c00818dd7..110b1138ea9 100644 --- a/hotspot/.mx.jvmci/suite.py +++ b/hotspot/.mx.jvmci/suite.py @@ -1,5 +1,5 @@ suite = { - "mxversion" : "5.6.11", + "mxversion" : "5.6.16", "name" : "jvmci", "url" : "http://openjdk.java.net/projects/graal", "developer" : { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java index 0038c161b1b..a45a003cae0 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java @@ -76,14 +76,14 @@ public class AArch64 extends Architecture { public static final Register zr = r31; public static final Register sp = r31; + // @formatter:off public static final Register[] cpuRegisters = { - // @formatter:off r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31 - // @formatter:on }; + // @formatter:on public static final RegisterCategory SIMD = new RegisterCategory("SIMD"); @@ -121,17 +121,17 @@ public class AArch64 extends Architecture { public static final Register v30 = new Register(62, 30, "v30", SIMD); public static final Register v31 = new Register(63, 31, "v31", SIMD); + // @formatter:off public static final Register[] simdRegisters = { - // @formatter:off v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 - // @formatter:on }; + // @formatter:on + // @formatter:off public static final Register[] allRegisters = { - // @formatter:off r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, @@ -141,14 +141,14 @@ public class AArch64 extends Architecture { v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 - // @formatter:on }; + // @formatter:on /** * Basic set of CPU features mirroring what is returned from the cpuid instruction. See: * {@code VM_Version::cpuFeatureFlags}. */ - public static enum CPUFeature { + public enum CPUFeature { FP, ASIMD, EVTSTRM, @@ -166,7 +166,7 @@ public class AArch64 extends Architecture { /** * Set of flags to control code emission. */ - public static enum Flag { + public enum Flag { UseBarriersForVolatile, UseCRC32, UseNeon diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64Kind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64Kind.java index 1802ef7eab2..c996fdb9f2d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64Kind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64Kind.java @@ -58,13 +58,13 @@ public enum AArch64Kind implements PlatformKind { private final AArch64Kind scalar; private final EnumKey key = new EnumKey<>(this); - private AArch64Kind(int size) { + AArch64Kind(int size) { this.size = size; this.scalar = this; this.vectorLength = 1; } - private AArch64Kind(int size, AArch64Kind scalar) { + AArch64Kind(int size, AArch64Kind scalar) { this.size = size; this.scalar = scalar; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java index b9ce1192221..37393ff08bc 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java @@ -169,7 +169,7 @@ public class AMD64 extends Architecture { * Basic set of CPU features mirroring what is returned from the cpuid instruction. See: * {@code VM_Version::cpuFeatureFlags}. */ - public static enum CPUFeature { + public enum CPUFeature { CX8, CMOV, FXSR, @@ -210,7 +210,7 @@ public class AMD64 extends Architecture { /** * Set of flags to control code emission. */ - public static enum Flag { + public enum Flag { UseCountLeadingZerosInstruction, UseCountTrailingZerosInstruction } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java index 3896bea7f4f..df69b120463 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java @@ -74,13 +74,13 @@ public enum AMD64Kind implements PlatformKind { private final AMD64Kind scalar; private final EnumKey key = new EnumKey<>(this); - private AMD64Kind(int size) { + AMD64Kind(int size) { this.size = size; this.scalar = this; this.vectorLength = 1; } - private AMD64Kind(int size, AMD64Kind scalar) { + AMD64Kind(int size, AMD64Kind scalar) { this.size = size; this.scalar = scalar; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java index efd65fa4921..33f875483d1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java @@ -23,7 +23,7 @@ package jdk.vm.ci.code; /** - * Class representing a exception with a stack trace of the currently processed position in the + * Class representing an exception with a stack trace of the currently processed position in the * compiled Java program instead of the stack trace of the compiler. The exception of the compiler * is saved as the cause of this exception. */ @@ -36,7 +36,7 @@ public abstract class SourceStackTrace extends BailoutException { private static final long serialVersionUID = 6279381376051787907L; @Override - public final synchronized Throwable fillInStackTrace() { + public synchronized Throwable fillInStackTrace() { assert elements != null; setStackTrace(elements); return this; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java index 357a4a23050..b554f173972 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCallingConventionType.java @@ -49,7 +49,7 @@ public enum HotSpotCallingConventionType implements CallingConvention.Type { public static final Type[] VALUES = values(); - private HotSpotCallingConventionType(boolean out) { + HotSpotCallingConventionType(boolean out) { this.out = out; } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java index 0885a2dcded..6cfa01289f1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java @@ -126,7 +126,7 @@ final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, Metas private static final int InternalMin = config().jvmConstantInternalMin; private static final int InternalMax = config().jvmConstantInternalMax; - private JVM_CONSTANT(int tag) { + JVM_CONSTANT(int tag) { this.tag = tag; } @@ -171,7 +171,7 @@ final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, Metas int lastCpi = Integer.MIN_VALUE; JavaType javaType; - public LookupTypeCacheElement(int lastCpi, JavaType javaType) { + LookupTypeCacheElement(int lastCpi, JavaType javaType) { super(); this.lastCpi = lastCpi; this.javaType = javaType; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 88711cc3cb8..afdc02fe26f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -43,6 +43,7 @@ import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.inittimer.InitTimer; +import jdk.vm.ci.inittimer.SuppressFBWarnings; import jdk.vm.ci.meta.JVMCIMetaAccessContext; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; @@ -115,7 +116,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H private boolean isDefault; private final String help; - private Option(Class type, Object defaultValue, String help) { + Option(Class type, Object defaultValue, String help) { assert Character.isUpperCase(name().charAt(0)) : "Option name must start with upper-case letter: " + name(); this.type = type; this.value = UNINITIALIZED; @@ -123,6 +124,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H this.help = help; } + @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum") private Object getValue() { if (value == UNINITIALIZED) { String propertyValue = VM.getSavedProperty(JVMCI_OPTION_PROPERTY_PREFIX + name()); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java index 953f00f9884..44e7c64cc19 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java @@ -38,7 +38,7 @@ class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider, Ho protected final HotSpotJVMCIRuntimeProvider runtime; - public HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) { + HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) { this.runtime = runtime; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java index 1741a080720..f42f9aff6ab 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -413,7 +413,7 @@ public final class HotSpotMethodData { private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1); private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset); - public CounterData() { + CounterData() { super(Tag.CounterData, COUNTER_DATA_SIZE); } @@ -442,7 +442,7 @@ public final class HotSpotMethodData { protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset); protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset); - public JumpData() { + JumpData() { super(Tag.JumpData, JUMP_DATA_SIZE); } @@ -476,7 +476,7 @@ public final class HotSpotMethodData { final long[] counts; final long totalCount; - public RawItemProfile(int entries, T[] items, long[] counts, long totalCount) { + RawItemProfile(int entries, T[] items, long[] counts, long totalCount) { this.entries = entries; this.items = items; this.counts = counts; @@ -587,7 +587,7 @@ public final class HotSpotMethodData { private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; - public ReceiverTypeData() { + ReceiverTypeData() { super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE); } @@ -612,7 +612,7 @@ public final class HotSpotMethodData { private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth; - public VirtualCallData() { + VirtualCallData() { super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE); } @@ -714,7 +714,7 @@ public final class HotSpotMethodData { private static class VirtualCallTypeData extends VirtualCallData { - public VirtualCallTypeData() { + VirtualCallTypeData() { super(Tag.VirtualCallTypeData, 0); } @@ -730,7 +730,7 @@ public final class HotSpotMethodData { private static final int RET_DATA_ROW_SIZE = cellsToBytes(3); private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth; - public RetData() { + RetData() { super(Tag.RetData, RET_DATA_SIZE); } } @@ -740,7 +740,7 @@ public final class HotSpotMethodData { private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3); private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset); - public BranchData() { + BranchData() { super(Tag.BranchData, BRANCH_DATA_SIZE); } @@ -773,7 +773,7 @@ public final class HotSpotMethodData { private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset); protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset); - public ArrayData(Tag tag, int staticSize) { + ArrayData(Tag tag, int staticSize) { super(tag, staticSize); } @@ -800,7 +800,7 @@ public final class HotSpotMethodData { private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0); private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1); - public MultiBranchData() { + MultiBranchData() { super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE); } @@ -882,13 +882,13 @@ public final class HotSpotMethodData { private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1); - public ArgInfoData() { + ArgInfoData() { super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE); } } private static class UnknownProfileData extends AbstractMethodData { - public UnknownProfileData(Tag tag) { + UnknownProfileData(Tag tag) { super(tag, 0); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java index 7ac97ebb59f..baf175f0e9a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java @@ -56,7 +56,7 @@ public interface HotSpotMethodDataAccessor { private final int value; - private Tag(int value) { + Tag(int value) { this.value = value; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java index b859c124a4d..e68c7fef8c1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java @@ -34,7 +34,7 @@ final class HotSpotMethodUnresolved extends HotSpotMethod { private final Signature signature; protected JavaType holder; - public HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) { + HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) { super(name); this.holder = holder; this.signature = signature; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index f516412fa6e..6762eced201 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -56,7 +56,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotP public static class FieldLocationIdentity extends LocationIdentity { HotSpotResolvedJavaField inner; - public FieldLocationIdentity(HotSpotResolvedJavaFieldImpl inner) { + FieldLocationIdentity(HotSpotResolvedJavaFieldImpl inner) { this.inner = inner; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 3b1dc5abf9f..69f9714a517 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -553,7 +553,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem * * @param index index to the fields array */ - public FieldInfo(int index) { + FieldInfo(int index) { HotSpotVMConfig config = config(); // Get Klass::_fields final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index ae0302b87fb..5f9c68c1685 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -360,7 +360,7 @@ public class HotSpotVMConfig { private final long address; - public VMFields(long address) { + VMFields(long address) { this.address = address; } @@ -477,7 +477,7 @@ public class HotSpotVMConfig { private final long address; - public VMTypes(long address) { + VMTypes(long address) { this.address = address; } @@ -580,7 +580,7 @@ public class HotSpotVMConfig { private final long address; - public VMIntConstants(long address) { + VMIntConstants(long address) { this.address = address; } @@ -639,7 +639,7 @@ public class HotSpotVMConfig { private final long address; - public VMLongConstants(long address) { + VMLongConstants(long address) { this.address = address; } @@ -698,7 +698,7 @@ public class HotSpotVMConfig { private final long address; - public VMAddresses(long address) { + VMAddresses(long address) { this.address = address; } @@ -753,7 +753,7 @@ public class HotSpotVMConfig { private final long nameOffset; private final long addrOffset; - public Flags(HashMap vmStructs, HashMap vmTypes) { + Flags(HashMap vmStructs, HashMap vmTypes) { address = vmStructs.get("Flag::flags").getValue(); entrySize = vmTypes.get("Flag").getSize(); typeOffset = vmStructs.get("Flag::_type").getOffset(); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationAction.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationAction.java index 70ebd06348a..0438b95e9be 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationAction.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DeoptimizationAction.java @@ -59,7 +59,7 @@ public enum DeoptimizationAction { private final boolean invalidatesCompilation; - private DeoptimizationAction(boolean invalidatesCompilation) { + DeoptimizationAction(boolean invalidatesCompilation) { this.invalidatesCompilation = invalidatesCompilation; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java index bd8df8299c2..69fefbfb4ee 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java @@ -72,7 +72,7 @@ public enum JavaKind { private final Class boxedJavaClass; private final int slotCount; - private JavaKind(char typeChar, String javaName, int slotCount, boolean isStackInt, Class primitiveJavaClass, Class boxedJavaClass) { + JavaKind(char typeChar, String javaName, int slotCount, boolean isStackInt, Class primitiveJavaClass, Class boxedJavaClass) { this.typeChar = typeChar; this.javaName = javaName; this.slotCount = slotCount; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java index 220c17555c6..9ac93d9c944 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java @@ -57,7 +57,7 @@ import java.util.ArrayList; */ public final class LIRKind { - private static enum IllegalKind implements PlatformKind { + private enum IllegalKind implements PlatformKind { ILLEGAL; private final EnumKey key = new EnumKey<>(this); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java index 8397fef5f08..a6d26e9aeab 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java @@ -35,7 +35,7 @@ public interface MethodHandleAccessProvider { * Identification for methods defined on the class {@link MethodHandle} that are processed by * the {@link MethodHandleAccessProvider}. */ - public enum IntrinsicMethod { + enum IntrinsicMethod { /** The method {@code MethodHandle.invokeBasic}. */ INVOKE_BASIC, /** The method {@code MethodHandle.linkToStatic}. */ diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java index 6947c9aefea..07a60c2aeba 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java @@ -33,7 +33,7 @@ public interface PlatformKind { } - public class EnumKey> implements Key { + class EnumKey> implements Key { private final Enum e; public EnumKey(Enum e) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java index 0e2fcae46b5..879322e0228 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java @@ -47,13 +47,13 @@ public enum SPARCKind implements PlatformKind { private final SPARCKind scalar; private final EnumKey key = new EnumKey<>(this); - private SPARCKind(int size) { + SPARCKind(int size) { this.size = size; this.scalar = this; this.vectorLength = 1; } - private SPARCKind(int size, SPARCKind scalar) { + SPARCKind(int size, SPARCKind scalar) { this.size = size; this.scalar = scalar; diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java index d7fc033158e..055ded60645 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java @@ -39,7 +39,7 @@ class NameAndSignature { final Class returnType; final Class[] parameterTypes; - public NameAndSignature(Method m) { + NameAndSignature(Method m) { this.name = m.getName(); this.returnType = m.getReturnType(); this.parameterTypes = m.getParameterTypes(); diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 3fa46c10196..8c869808338 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -500,7 +500,7 @@ public class TestResolvedJavaType extends TypeUniverse { final Method implementation; final Set declarations; - public Declarations(Method impl) { + Declarations(Method impl) { this.implementation = impl; declarations = new HashSet<>(); } From 7fa54e38e65f046305398180370e920535809985 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 29 Jan 2016 17:18:35 +0100 Subject: [PATCH 083/139] 8137049: Code quality: reducing an trivial integer loop does not produce an optimal code Canonicalized if shape not recognized by empty loop detection code Reviewed-by: kvn, shade --- hotspot/src/share/vm/opto/loopTransform.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index c07a4f5c121..ae605c05996 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -2404,15 +2404,25 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { if (needs_guard) { // Check for an obvious zero trip guard. Node* inctrl = PhaseIdealLoop::skip_loop_predicates(cl->in(LoopNode::EntryControl)); - if (inctrl->Opcode() == Op_IfTrue) { + if (inctrl->Opcode() == Op_IfTrue || inctrl->Opcode() == Op_IfFalse) { + bool maybe_swapped = (inctrl->Opcode() == Op_IfFalse); // The test should look like just the backedge of a CountedLoop Node* iff = inctrl->in(0); if (iff->is_If()) { Node* bol = iff->in(1); - if (bol->is_Bool() && bol->as_Bool()->_test._test == cl->loopexit()->test_trip()) { - Node* cmp = bol->in(1); - if (cmp->is_Cmp() && cmp->in(1) == cl->init_trip() && cmp->in(2) == cl->limit()) { - needs_guard = false; + if (bol->is_Bool()) { + BoolTest test = bol->as_Bool()->_test; + if (maybe_swapped) { + test._test = test.commute(); + test._test = test.negate(); + } + if (test._test == cl->loopexit()->test_trip()) { + Node* cmp = bol->in(1); + int init_idx = maybe_swapped ? 2 : 1; + int limit_idx = maybe_swapped ? 1 : 2; + if (cmp->is_Cmp() && cmp->in(init_idx) == cl->init_trip() && cmp->in(limit_idx) == cl->limit()) { + needs_guard = false; + } } } } From a7de801a928f183e8acc87ecba488e2772577239 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Wed, 3 Feb 2016 11:34:12 +0000 Subject: [PATCH 084/139] 8148948: aarch64: generate_copy_longs calls align() incorrectly Fix alignments Reviewed-by: aph --- hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp | 4 ---- hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index b6a58d9a371..7678cf263e4 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -40,11 +40,7 @@ define_pd_global(bool, ImplicitNullChecks, true); // Generate code for im define_pd_global(bool, TrapBasedNullChecks, false); define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast -#if defined(COMPILER2) || INCLUDE_JVMCI define_pd_global(intx, CodeEntryAlignment, 64); -#else -define_pd_global(intx, CodeEntryAlignment, 16); -#endif // COMPILER2 define_pd_global(intx, OptoLoopAlignment, 16); define_pd_global(intx, InlineFrequencyCount, 100); diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 65abe139076..68c7dd1d8c0 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -791,7 +791,7 @@ class StubGenerator: public StubCodeGenerator { assert_different_registers(s, d, count, rscratch1); Label again, large, small; - __ align(6); + __ align(CodeEntryAlignment); __ bind(start); __ cmp(count, 8); __ br(Assembler::LO, small); @@ -836,7 +836,7 @@ class StubGenerator: public StubCodeGenerator { __ ret(lr); - __ align(6); + __ align(CodeEntryAlignment); __ bind(large); // Fill 8 registers From eaaec5b8794f8f2221b37ecf9cb151f6b9f5c947 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Thu, 4 Feb 2016 16:24:28 +0000 Subject: [PATCH 085/139] 8148783: aarch64: SEGV running SpecJBB2013 Fix calculation of offset for adrp Reviewed-by: aph --- .../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index b1b9a55df1b..40c55140c92 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -127,7 +127,10 @@ int MacroAssembler::pd_patch_instruction_size(address branch, address target) { Instruction_aarch64::extract(insn2, 4, 0)) { // movk #imm16<<32 Instruction_aarch64::patch(branch + 4, 20, 5, (uint64_t)target >> 32); - offset &= (1<<20)-1; + long dest = ((long)target & 0xffffffffL) | ((long)branch & 0xffff00000000L); + long pc_page = (long)branch >> 12; + long adr_page = (long)dest >> 12; + offset = adr_page - pc_page; instructions = 2; } } @@ -3998,11 +4001,12 @@ void MacroAssembler::adrp(Register reg1, const Address &dest, unsigned long &byt if (offset_high >= -(1<<20) && offset_low < (1<<20)) { _adrp(reg1, dest.target()); } else { - unsigned long pc_page = (unsigned long)pc() >> 12; - long offset = dest_page - pc_page; - offset = (offset & ((1<<20)-1)) << 12; - _adrp(reg1, pc()+offset); - movk(reg1, (unsigned long)dest.target() >> 32, 32); + unsigned long target = (unsigned long)dest.target(); + unsigned long adrp_target + = (target & 0xffffffffUL) | ((unsigned long)pc() & 0xffff00000000UL); + + _adrp(reg1, (address)adrp_target); + movk(reg1, target >> 32, 32); } byte_offset = (unsigned long)dest.target() & 0xfff; } From 4c5566f502f2ad53994c876017c19d49267b3bc1 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Mon, 8 Feb 2016 14:14:35 +0000 Subject: [PATCH 086/139] 8149365: aarch64: memory copy does not prefetch on backwards copy Implement prefetch on backwards copies Reviewed-by: aph --- .../src/cpu/aarch64/vm/stubGenerator_aarch64.cpp | 13 +++++++++++-- hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp | 9 ++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 68c7dd1d8c0..a0e0c12a9dd 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -786,6 +786,7 @@ class StubGenerator: public StubCodeGenerator { int offset; const Register t0 = r3, t1 = r4, t2 = r5, t3 = r6, t4 = r7, t5 = r10, t6 = r11, t7 = r12; + const Register stride = r13; assert_different_registers(rscratch1, t0, t1, t2, t3, t4, t5, t6, t7); assert_different_registers(s, d, count, rscratch1); @@ -845,10 +846,18 @@ class StubGenerator: public StubCodeGenerator { __ ldp(t4, t5, Address(s, 6 * unit)); __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + int prefetch = PrefetchCopyIntervalInBytes; + bool use_stride = false; + if (direction == copy_backwards) { + use_stride = prefetch > 256; + prefetch = -prefetch; + if (use_stride) __ mov(stride, prefetch); + } + __ bind(again); - if (direction == copy_forwards && PrefetchCopyIntervalInBytes > 0) - __ prfm(Address(s, PrefetchCopyIntervalInBytes), PLDL1KEEP); + if (PrefetchCopyIntervalInBytes > 0) + __ prfm(use_stride ? Address(s, stride) : Address(s, prefetch), PLDL1KEEP); __ stp(t0, t1, Address(d, 2 * unit)); __ ldp(t0, t1, Address(s, 2 * unit)); diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp index 6de94bee33d..21859656b52 100644 --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp @@ -120,7 +120,14 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(AllocatePrefetchStepSize, 64); FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 256); FLAG_SET_DEFAULT(PrefetchFieldsAhead, 256); - FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 256); + if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes)) + FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 256); + if ((PrefetchCopyIntervalInBytes & 7) || (PrefetchCopyIntervalInBytes >= 32768)) { + warning("PrefetchCopyIntervalInBytes must be a multiple of 8 and < 32768"); + PrefetchCopyIntervalInBytes &= ~7; + if (PrefetchCopyIntervalInBytes >= 32768) + PrefetchCopyIntervalInBytes = 32760; + } unsigned long auxv = getauxval(AT_HWCAP); From 9ad1ef5b10f85841da9aa860bfeaa54491628fdc Mon Sep 17 00:00:00 2001 From: Hui Shi Date: Sat, 6 Feb 2016 04:09:47 -0800 Subject: [PATCH 087/139] 8149100: AArch64: "bad AD file" for LL enconding AryEq Node matching Add byte array equal support for aarch64 Reviewed-by: aph --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 17 ++++- .../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 76 +++++++++++++++++++ .../cpu/aarch64/vm/macroAssembler_aarch64.hpp | 2 + 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 2b5d3d8838d..e94d23c150e 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -14928,7 +14928,22 @@ instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, ins_pipe(pipe_class_memory); %} -instruct array_equals(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, +instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, + iRegP_R10 tmp, rFlagsReg cr) +%{ + predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (AryEq ary1 ary2)); + effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr); + + format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} + ins_encode %{ + __ byte_arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register); + %} + ins_pipe(pipe_class_memory); +%} + +instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr) %{ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 40c55140c92..97c2c14583a 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -4561,6 +4561,82 @@ void MacroAssembler::string_equals(Register str1, Register str2, BLOCK_COMMENT("} string_equals"); } + +void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2, + Register result, Register tmp1) +{ + Register cnt1 = rscratch1; + Register cnt2 = rscratch2; + Register tmp2 = rscratch2; + + Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01; + + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); + + BLOCK_COMMENT("byte_arrays_equals {"); + + // different until proven equal + mov(result, false); + + // same array? + cmp(ary1, ary2); + br(Assembler::EQ, SAME); + + // ne if either null + cbz(ary1, DIFFER); + cbz(ary2, DIFFER); + + // lengths ne? + ldrw(cnt1, Address(ary1, length_offset)); + ldrw(cnt2, Address(ary2, length_offset)); + cmp(cnt1, cnt2); + br(Assembler::NE, DIFFER); + + lea(ary1, Address(ary1, base_offset)); + lea(ary2, Address(ary2, base_offset)); + + subs(cnt1, cnt1, 8); + br(LT, TAIL07); + + BIND(NEXT); + ldr(tmp1, Address(post(ary1, 8))); + ldr(tmp2, Address(post(ary2, 8))); + subs(cnt1, cnt1, 8); + eor(tmp1, tmp1, tmp2); + cbnz(tmp1, DIFFER); + br(GE, NEXT); + + BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4 + tst(cnt1, 0b100); + br(EQ, TAIL03); + ldrw(tmp1, Address(post(ary1, 4))); + ldrw(tmp2, Address(post(ary2, 4))); + cmp(tmp1, tmp2); + br(NE, DIFFER); + + BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4 + tst(cnt1, 0b10); + br(EQ, TAIL01); + ldrh(tmp1, Address(post(ary1, 2))); + ldrh(tmp2, Address(post(ary2, 2))); + cmp(tmp1, tmp2); + br(NE, DIFFER); + BIND(TAIL01); // 0-1 byte left + tst(cnt1, 0b01); + br(EQ, SAME); + ldrb(tmp1, ary1); + ldrb(tmp2, ary2); + cmp(tmp1, tmp2); + br(NE, DIFFER); + + BIND(SAME); + mov(result, true); + BIND(DIFFER); // result already set + + BLOCK_COMMENT("} byte_arrays_equals"); +} + // Compare char[] arrays aligned to 4 bytes void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, Register result, Register tmp1) diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index 4256d3a0989..d22c581bc41 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -1191,6 +1191,8 @@ public: Register tmp1); void char_arrays_equals(Register ary1, Register ary2, Register result, Register tmp1); + void byte_arrays_equals(Register ary1, Register ary2, + Register result, Register tmp1); void encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, From 663e1a5c6d4e15942cd7fa01a567b5d508927b22 Mon Sep 17 00:00:00 2001 From: Hui Shi Date: Fri, 5 Feb 2016 03:55:51 -0800 Subject: [PATCH 088/139] 8149080: AArch64: Recognise disjoint array copy in stub code Detect array copy can use fwd copy by checking (dest-src) above_same (copy_size) Reviewed-by: aph --- .../src/cpu/aarch64/vm/stubGenerator_aarch64.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index a0e0c12a9dd..554495da44e 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -792,6 +792,12 @@ class StubGenerator: public StubCodeGenerator { assert_different_registers(s, d, count, rscratch1); Label again, large, small; + const char *stub_name; + if (direction == copy_forwards) + stub_name = "foward_copy_longs"; + else + stub_name = "backward_copy_longs"; + StubCodeMark mark(this, "StubRoutines", stub_name); __ align(CodeEntryAlignment); __ bind(start); __ cmp(count, 8); @@ -1160,8 +1166,11 @@ class StubGenerator: public StubCodeGenerator { // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) BLOCK_COMMENT("Entry:"); } - __ cmp(d, s); - __ br(Assembler::LS, nooverlap_target); + + // use fwd copy when (d-s) above_equal (count*size) + __ sub(rscratch1, d, s); + __ cmp(rscratch1, count, Assembler::LSL, exact_log2(size)); + __ br(Assembler::HS, nooverlap_target); if (is_oop) { __ push(RegSet::of(d, count), sp); From 75826ca4d5ac235110a86666c5b0e92c2000a2f4 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 8 Feb 2016 18:26:27 +0300 Subject: [PATCH 089/139] 8149184: os::is_server_class_machine() could return incorrect result if a host's cpu have a few logical cores Reviewed-by: dsamersoff, dholmes --- hotspot/src/share/vm/runtime/os.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 699914032ff..5aedae5bf57 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1490,7 +1490,7 @@ bool os::is_server_class_machine() { if (logical_processors > 1) { const unsigned int physical_packages = os::active_processor_count() / logical_processors; - if (physical_packages > server_processors) { + if (physical_packages >= server_processors) { result = true; } } else { From 7cf2c51fa74e03d932bf4afe7fb8a7b1b4a494dd Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Mon, 8 Feb 2016 18:52:03 +0100 Subject: [PATCH 090/139] 8148741: compiler/jvmci/code/SimpleDebugInfoTest.java fails in 'frame::sender_for_compiled_frame' Reviewed-by: twisti --- .../vm/ci/hotspot/HotSpotForeignCallTarget.java | 6 ++++-- .../jvmci/code/CodeInstallationTest.java | 1 + .../test/compiler/jvmci/code/TestAssembler.java | 16 ++++++++++++++++ .../jvmci/code/amd64/AMD64TestAssembler.java | 11 +++++++++++ .../jvmci/code/sparc/SPARCTestAssembler.java | 10 ++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java index b13958b6995..2b4d0e1166f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 +22,9 @@ */ package jdk.vm.ci.hotspot; -public class HotSpotForeignCallTarget { +import jdk.vm.ci.meta.InvokeTarget; + +public class HotSpotForeignCallTarget implements InvokeTarget { /** * The entry point address of this call's target. diff --git a/hotspot/test/compiler/jvmci/code/CodeInstallationTest.java b/hotspot/test/compiler/jvmci/code/CodeInstallationTest.java index aa0899ed256..550665cf342 100644 --- a/hotspot/test/compiler/jvmci/code/CodeInstallationTest.java +++ b/hotspot/test/compiler/jvmci/code/CodeInstallationTest.java @@ -92,6 +92,7 @@ public class CodeInstallationTest { asm.emitPrologue(); compiler.compile(asm); + asm.emitEpilogue(); HotSpotCompiledCode code = asm.finish(resolvedMethod); InstalledCode installed = codeCache.addCode(resolvedMethod, code, null, null); diff --git a/hotspot/test/compiler/jvmci/code/TestAssembler.java b/hotspot/test/compiler/jvmci/code/TestAssembler.java index d9a15ac2dc5..5034027a762 100644 --- a/hotspot/test/compiler/jvmci/code/TestAssembler.java +++ b/hotspot/test/compiler/jvmci/code/TestAssembler.java @@ -32,11 +32,13 @@ import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.StackSlot; +import jdk.vm.ci.code.site.Call; import jdk.vm.ci.code.site.ConstantReference; import jdk.vm.ci.code.site.DataPatch; import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.code.site.Infopoint; import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.code.site.Mark; import jdk.vm.ci.code.site.Reference; import jdk.vm.ci.code.site.Site; import jdk.vm.ci.hotspot.HotSpotCompiledCode; @@ -45,6 +47,7 @@ import jdk.vm.ci.hotspot.HotSpotCompiledNmethod; import jdk.vm.ci.hotspot.HotSpotConstant; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.meta.InvokeTarget; import jdk.vm.ci.meta.LIRKind; import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -60,6 +63,11 @@ public abstract class TestAssembler { */ public abstract void emitPrologue(); + /** + * Emit the method epilogue code (e.g. the deopt handler). + */ + public abstract void emitEpilogue(); + /** * Emit code to grow the stack frame. * @@ -222,6 +230,14 @@ public abstract class TestAssembler { this.deoptRescue = deoptRescue; } + protected void recordCall(InvokeTarget target, int size, boolean direct, DebugInfo debugInfo) { + sites.add(new Call(target, code.position(), size, direct, debugInfo)); + } + + protected void recordMark(Object id) { + sites.add(new Mark(code.position(), id)); + } + protected void recordImplicitException(DebugInfo info) { sites.add(new Infopoint(code.position(), info, InfopointReason.IMPLICIT_EXCEPTION)); } diff --git a/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java b/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java index 80bf2d17fd1..4ed0625932b 100644 --- a/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java +++ b/hotspot/test/compiler/jvmci/code/amd64/AMD64TestAssembler.java @@ -33,6 +33,8 @@ import jdk.vm.ci.code.site.ConstantReference; import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotForeignCallTarget; +import jdk.vm.ci.hotspot.HotSpotVMConfig; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.LIRKind; import jdk.vm.ci.meta.VMConstant; @@ -66,6 +68,15 @@ public class AMD64TestAssembler extends TestAssembler { setDeoptRescueSlot(newStackSlot(LIRKind.value(AMD64Kind.QWORD))); } + @Override + public void emitEpilogue() { + HotSpotVMConfig config = HotSpotVMConfig.config(); + recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); + recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 5, true, null); + code.emitByte(0xE8); // CALL rel32 + code.emitInt(0xDEADDEAD); + } + @Override public void emitGrowStack(int size) { // SUB rsp, size diff --git a/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java b/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java index d0bcc9c013c..5b2cd7f1453 100644 --- a/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java +++ b/hotspot/test/compiler/jvmci/code/sparc/SPARCTestAssembler.java @@ -32,7 +32,9 @@ import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotForeignCallTarget; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotVMConfig; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.LIRKind; import jdk.vm.ci.meta.VMConstant; @@ -71,6 +73,14 @@ public class SPARCTestAssembler extends TestAssembler { setDeoptRescueSlot(newStackSlot(LIRKind.value(SPARCKind.XWORD))); } + @Override + public void emitEpilogue() { + HotSpotVMConfig config = HotSpotVMConfig.config(); + recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); + recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 4, true, null); + code.emitInt(1 << 30); // CALL + } + @Override public HotSpotCompiledCode finish(HotSpotResolvedJavaMethod method) { frameSize += SPARC.REGISTER_SAFE_AREA_SIZE; From 075ed4ea75c4295a7f82c2f03984beb8585f4e2f Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 8 Feb 2016 18:52:03 +0100 Subject: [PATCH 091/139] 8148507: [JVMCI] mitigate deadlocks related to JVMCI compiler under -Xbatch Reviewed-by: twisti, dholmes --- .../src/share/vm/compiler/compileBroker.cpp | 73 ++++++++++--------- .../src/share/vm/compiler/compileBroker.hpp | 5 +- hotspot/src/share/vm/jvmci/jvmciCompiler.cpp | 8 +- hotspot/src/share/vm/jvmci/jvmciCompiler.hpp | 13 ++-- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 7f9868986af..c74b727c333 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -545,7 +545,7 @@ void CompileBroker::compilation_init(TRAPS) { c1_count = JVMCIHostThreads; } - if (!UseInterpreter) { + if (!UseInterpreter || !BackgroundCompilation) { // Force initialization of JVMCI compiler otherwise JVMCI // compilations will not block until JVMCI is initialized ResourceMark rm; @@ -1346,49 +1346,55 @@ CompileTask* CompileBroker::create_compile_task(CompileQueue* queue, } #if INCLUDE_JVMCI -// The number of milliseconds to wait before checking if the -// JVMCI compiler thread is blocked. -static const long BLOCKING_JVMCI_COMPILATION_WAIT_TIMESLICE = 500; +// The number of milliseconds to wait before checking if +// JVMCI compilation has made progress. +static const long JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE = 500; -// The number of successive times the above check is allowed to -// see a blocked JVMCI compiler thread before unblocking the -// thread waiting for the compilation to finish. -static const int BLOCKING_JVMCI_COMPILATION_WAIT_TO_UNBLOCK_ATTEMPTS = 5; +// The number of JVMCI compilation progress checks that must fail +// before unblocking a thread waiting for a blocking compilation. +static const int JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS = 5; /** * Waits for a JVMCI compiler to complete a given task. This thread - * waits until either the task completes or it sees the JVMCI compiler - * thread is blocked for N consecutive milliseconds where N is - * BLOCKING_JVMCI_COMPILATION_WAIT_TIMESLICE * - * BLOCKING_JVMCI_COMPILATION_WAIT_TO_UNBLOCK_ATTEMPTS. + * waits until either the task completes or it sees no JVMCI compilation + * progress for N consecutive milliseconds where N is + * JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE * + * JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS. * * @return true if this thread needs to free/recycle the task */ -bool CompileBroker::wait_for_jvmci_completion(CompileTask* task, JavaThread* thread) { +bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask* task, JavaThread* thread) { MutexLocker waiter(task->lock(), thread); - int consecutively_blocked = 0; - while (task->lock()->wait(!Mutex::_no_safepoint_check_flag, BLOCKING_JVMCI_COMPILATION_WAIT_TIMESLICE)) { + int progress_wait_attempts = 0; + int methods_compiled = jvmci->methods_compiled(); + while (!task->is_complete() && !is_compilation_disabled_forever() && + task->lock()->wait(!Mutex::_no_safepoint_check_flag, JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) { CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread(); + + bool progress; if (jvmci_compiler_thread != NULL) { - JavaThreadState state; - { - // A JVMCI compiler thread should not disappear at this point - // but let's be extra safe. - MutexLocker mu(Threads_lock, thread); - state = jvmci_compiler_thread->thread_state(); - } - if (state == _thread_blocked) { - if (++consecutively_blocked == BLOCKING_JVMCI_COMPILATION_WAIT_TO_UNBLOCK_ATTEMPTS) { - if (PrintCompilation) { - task->print(tty, "wait for blocking compilation timed out"); - } - break; + // If the JVMCI compiler thread is not blocked, we deem it to be making progress. + progress = jvmci_compiler_thread->thread_state() != _thread_blocked; + } else { + // Still waiting on JVMCI compiler queue. This thread may be holding a lock + // that all JVMCI compiler threads are blocked on. We use the counter for + // successful JVMCI compilations to determine whether JVMCI compilation + // is still making progress through the JVMCI compiler queue. + progress = jvmci->methods_compiled() != methods_compiled; + } + + if (!progress) { + if (++progress_wait_attempts == JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS) { + if (PrintCompilation) { + task->print(tty, "wait for blocking compilation timed out"); } - } else { - consecutively_blocked = 0; + break; } } else { - // Still waiting on JVMCI compiler queue + progress_wait_attempts = 0; + if (jvmci_compiler_thread == NULL) { + methods_compiled = jvmci->methods_compiled(); + } } } task->clear_waiter(); @@ -1413,8 +1419,9 @@ void CompileBroker::wait_for_completion(CompileTask* task) { methodHandle method(thread, task->method()); bool free_task; #if INCLUDE_JVMCI - if (compiler(task->comp_level())->is_jvmci()) { - free_task = wait_for_jvmci_completion(task, thread); + AbstractCompiler* comp = compiler(task->comp_level()); + if (comp->is_jvmci()) { + free_task = wait_for_jvmci_completion((JVMCICompiler*) comp, task, thread); } else #endif { diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index 92169d035a4..ba4db7d0cdd 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -32,6 +32,9 @@ #include "runtime/perfData.hpp" #include "trace/tracing.hpp" #include "utilities/stack.hpp" +#if INCLUDE_JVMCI +#include "jvmci/jvmciCompiler.hpp" +#endif class nmethod; class nmethodLocker; @@ -234,7 +237,7 @@ class CompileBroker: AllStatic { bool blocking); static void wait_for_completion(CompileTask* task); #if INCLUDE_JVMCI - static bool wait_for_jvmci_completion(CompileTask* task, JavaThread* thread); + static bool wait_for_jvmci_completion(JVMCICompiler* comp, CompileTask* task, JavaThread* thread); #endif static void invoke_compiler_on_method(CompileTask* task); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp index b9da75cde0d..429ccabbe6c 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp @@ -38,7 +38,7 @@ elapsedTimer JVMCICompiler::_codeInstallTimer; JVMCICompiler::JVMCICompiler() : AbstractCompiler(jvmci) { _bootstrapping = false; - _methodsCompiled = 0; + _methods_compiled = 0; assert(_instance == NULL, "only one instance allowed"); _instance = this; } @@ -99,7 +99,7 @@ void JVMCICompiler::bootstrap() { } while (first_round && qsize == 0); first_round = false; if (PrintBootstrap) { - while (z < (_methodsCompiled / 100)) { + while (z < (_methods_compiled / 100)) { ++z; tty->print_raw("."); } @@ -107,7 +107,7 @@ void JVMCICompiler::bootstrap() { } while (qsize != 0); if (PrintBootstrap) { - tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methodsCompiled); + tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methods_compiled); } _bootstrapping = false; } @@ -176,7 +176,7 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV env->set_failure("no nmethod produced", true); } else { env->task()->set_num_inlined_bytecodes(CompilationRequestResult::inlinedBytecodes(result_object)); - _methodsCompiled++; + Atomic::inc(&_methods_compiled); } } } else { diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp index fabee997500..44fbc48ea2d 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp @@ -33,10 +33,10 @@ private: bool _bootstrapping; /** - * Number of methods compiled by JVMCI. This is not synchronized - * so may not be 100% accurate. + * Number of methods successfully compiled by a call to + * JVMCICompiler::compile_method(). */ - volatile int _methodsCompiled; + volatile int _methods_compiled; static JVMCICompiler* _instance; @@ -80,8 +80,11 @@ public: // Print compilation timers and statistics virtual void print_timers(); - // Print compilation statistics - void reset_compilation_stats(); + /** + * Gets the number of methods that have been successfully compiled by + * a call to JVMCICompiler::compile_method(). + */ + int methods_compiled() { return _methods_compiled; } // Print compilation timers and statistics static void print_compilation_timers(); From 76628c45b945bfc8c8087f07efbcbbb85dd20ce2 Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Tue, 9 Feb 2016 12:19:05 +0100 Subject: [PATCH 092/139] 8149112: configure_stdout test depends on VM arguments Reviewed-by: ehelin, jbachorik --- hotspot/src/share/vm/logging/log.cpp | 45 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index c2741537826..ad86c39d6f9 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -30,6 +30,7 @@ #include "logging/log.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logOutput.hpp" #include "memory/resourceArea.hpp" void Test_log_length() { @@ -92,11 +93,47 @@ void Test_log_length() { remove("loglengthoutput.txt"); } +#define assert_str_eq(s1, s2) \ + assert(strcmp(s1, s2) == 0, "Expected '%s' to equal '%s'", s1, s2) + +#define assert_char_in(c, s) \ + assert(strchr(s, c) != NULL, "Expected '%s' to contain character '%c'", s, c) + +#define assert_char_not_in(c, s) \ + assert(strchr(s, c) == NULL, "Expected '%s' to *not* contain character '%c'", s, c) + void Test_configure_stdout() { + ResourceMark rm; + LogHandle(logging) log; + LogOutput* stdoutput = LogOutput::Stdout; + + // Save current stdout config and clear it + char* saved_config = os::strdup_check_oom(stdoutput->config_string()); + LogConfiguration::parse_log_arguments("stdout", "all=off", NULL, NULL, log.error_stream()); + + // Enable 'logging=info', verifying it has been set LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(logging)); - assert(log_is_enabled(Info, logging), "configure_stdout did not enable requested logging"); - assert(!log_is_enabled(Info, logging, gc), "configure_stdout enabled too much logging"); - LogConfiguration::configure_stdout(LogLevel::Off, false, LOG_TAGS(logging)); - assert(!log_is_enabled(Info, logging), "configure_stdout did not disable requested logging"); + assert_str_eq("logging=info,", stdoutput->config_string()); + assert(log_is_enabled(Info, logging), "logging was not properly enabled"); + + // Enable 'gc=debug' (no wildcard), verifying no other tags are enabled + LogConfiguration::configure_stdout(LogLevel::Debug, true, LOG_TAGS(gc)); + // No '+' character means only single tags are enabled, and no combinations + assert_char_not_in('+', stdoutput->config_string()); + assert(log_is_enabled(Debug, gc), "logging was not properly enabled"); + + // Enable 'gc*=trace' (with wildcard), verifying at least one tag combination is enabled (gc+...) + LogConfiguration::configure_stdout(LogLevel::Trace, false, LOG_TAGS(gc)); + assert_char_in('+', stdoutput->config_string()); + assert(log_is_enabled(Trace, gc), "logging was not properly enabled"); + + // Disable 'gc*' and 'logging', verifying all logging is properly disabled + LogConfiguration::configure_stdout(LogLevel::Off, false, LOG_TAGS(gc)); + LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(logging)); + assert_str_eq("all=off", stdoutput->config_string()); + + // Restore saved configuration + LogConfiguration::parse_log_arguments("stdout", saved_config, NULL, NULL, log.error_stream()); + os::free(saved_config); } #endif // PRODUCT From afca49ff295b27fcc26ff3bb34a9c86891b7a56f Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Wed, 10 Feb 2016 07:54:26 +0100 Subject: [PATCH 093/139] 8148752: Compiled StringBuilder code throws StringIndexOutOfBoundsException Fixed handling of long/double MH arguments in GraphBuilder::try_method_handle_inline(). Reviewed-by: roland, shade, vlivanov, kvn, twisti --- hotspot/src/share/vm/opto/callGenerator.cpp | 7 +- .../jsr292/LongReferenceCastingTest.java | 75 +++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 hotspot/test/compiler/jsr292/LongReferenceCastingTest.java diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 68a193e246c..8195cf49c75 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -867,17 +867,18 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* } } // Cast reference arguments to its type. - for (int i = 0; i < signature->count(); i++) { + for (int i = 0, j = 0; i < signature->count(); i++) { ciType* t = signature->type_at(i); if (t->is_klass()) { - Node* arg = kit.argument(receiver_skip + i); + Node* arg = kit.argument(receiver_skip + j); const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { Node* cast_obj = gvn.transform(new CheckCastPPNode(kit.control(), arg, sig_type)); - kit.set_argument(receiver_skip + i, cast_obj); + kit.set_argument(receiver_skip + j, cast_obj); } } + j += t->size(); // long and double take two slots } // Try to get the most accurate receiver type diff --git a/hotspot/test/compiler/jsr292/LongReferenceCastingTest.java b/hotspot/test/compiler/jsr292/LongReferenceCastingTest.java new file mode 100644 index 00000000000..218b096d2b7 --- /dev/null +++ b/hotspot/test/compiler/jsr292/LongReferenceCastingTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.invoke.*; + +/** + * @test + * @bug 8148752 + * @summary Test correct casting of MH arguments during inlining. + * @run main LongReferenceCastingTest + */ +public class LongReferenceCastingTest { + static final String MY_STRING = "myString"; + static final MethodHandle MH; + + static { + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(String.class, long.class, Object.class, String.class); + MH = lookup.findVirtual(LongReferenceCastingTest.class, "myMethod", mt); + } catch (Exception e) { + throw new Error(e); + } + } + + public String myMethod(long l, Object o, String s) { + // The long argument occupies two stack slots, causing C2 to treat it as + // two arguments and casting the fist one two long and the second one to Object. + // As a result, Object o is casted to String and the o.toString() call is + // inlined as String::toString(). We fail at runtime because 'o' is not a String. + return o.toString(); + } + + public String toString() { + return MY_STRING; + } + + public static void main(String[] args) throws Exception { + LongReferenceCastingTest test = new LongReferenceCastingTest(); + try { + for (int i = 0; i < 20_000; ++i) { + if (!test.invoke().equals(MY_STRING)) { + throw new RuntimeException("Invalid string"); + } + } + } catch (Throwable t) { + throw new RuntimeException("Test failed", t); + } + } + + public String invoke() throws Throwable { + return (String) MH.invokeExact(this, 0L, (Object)this, MY_STRING); + } +} From 1e80d261e3692e1037f6fc650a9673974f610de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Mon, 15 Feb 2016 17:02:32 +0100 Subject: [PATCH 094/139] 8147558: Add support for ES6 collections Reviewed-by: attila, mhaupt --- .../internal/tools/nasgen/ClassGenerator.java | 31 +- .../internal/tools/nasgen/MemberInfo.java | 5 +- .../tools/nasgen/StringConstants.java | 11 +- .../internal/objects/AbstractIterator.java | 196 ++++++++++++ .../internal/objects/ArrayIterator.java | 100 ++++++ .../jdk/nashorn/internal/objects/Global.java | 289 +++++++++++++++++- .../internal/objects/IteratorResult.java | 57 ++++ .../nashorn/internal/objects/LinkedMap.java | 239 +++++++++++++++ .../nashorn/internal/objects/MapIterator.java | 105 +++++++ .../nashorn/internal/objects/NativeArray.java | 44 +++ .../nashorn/internal/objects/NativeMap.java | 287 +++++++++++++++++ .../nashorn/internal/objects/NativeSet.java | 239 +++++++++++++++ .../internal/objects/NativeString.java | 11 + .../internal/objects/NativeSymbol.java | 8 + .../internal/objects/NativeWeakMap.java | 183 +++++++++++ .../internal/objects/NativeWeakSet.java | 143 +++++++++ .../nashorn/internal/objects/SetIterator.java | 99 ++++++ .../internal/objects/StringIterator.java | 98 ++++++ .../objects/annotations/Attribute.java | 22 +- .../internal/runtime/AccessorProperty.java | 7 +- .../internal/runtime/FindProperty.java | 2 +- .../nashorn/internal/runtime/Property.java | 21 ++ .../nashorn/internal/runtime/PropertyMap.java | 6 +- .../internal/runtime/ScriptFunction.java | 2 +- .../internal/runtime/ScriptObject.java | 29 +- .../internal/runtime/SetMethodCreator.java | 5 +- .../runtime/UserAccessorProperty.java | 3 +- .../runtime/linker/PrimitiveLookup.java | 11 +- .../runtime/resources/Messages.properties | 11 +- nashorn/test/script/basic/es6.js | 18 +- nashorn/test/script/basic/es6/iterator.js | 87 ++++++ nashorn/test/script/basic/es6/map.js | 195 ++++++++++++ nashorn/test/script/basic/es6/set.js | 173 +++++++++++ nashorn/test/script/basic/es6/weakmap.js | 100 ++++++ nashorn/test/script/basic/es6/weakset.js | 100 ++++++ 35 files changed, 2876 insertions(+), 61 deletions(-) create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/AbstractIterator.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/IteratorResult.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/LinkedMap.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/MapIterator.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeMap.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSet.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/SetIterator.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/StringIterator.java create mode 100644 nashorn/test/script/basic/es6/iterator.js create mode 100644 nashorn/test/script/basic/es6/map.js create mode 100644 nashorn/test/script/basic/es6/set.js create mode 100644 nashorn/test/script/basic/es6/weakmap.js create mode 100644 nashorn/test/script/basic/es6/weakset.js diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java index 5d45c38b878..f01a1d15eac 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java @@ -48,6 +48,7 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME; import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; import static jdk.nashorn.internal.tools.nasgen.StringConstants.LIST_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.NATIVESYMBOL_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; @@ -63,6 +64,8 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_S import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SETTER_PREFIX; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SYMBOL_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SYMBOL_PREFIX; import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_OBJECT; import java.io.BufferedInputStream; @@ -277,7 +280,7 @@ public class ClassGenerator { static void newFunction(final MethodGenerator mi, final String objName, final String className, final MemberInfo memInfo, final List specs) { final boolean arityFound = (memInfo.getArity() != MemberInfo.DEFAULT_ARITY); - mi.loadLiteral(memInfo.getName()); + loadFunctionName(mi, memInfo.getName()); mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, memInfo.getJavaName(), memInfo.getJavaDesc())); assert specs != null; @@ -305,8 +308,8 @@ public class ClassGenerator { // dup of Collection instance mi.dup(); - // property = AccessorProperty.create(key, flags, getter, setter); - mi.loadLiteral(propertyName); + // Load property name, converting to Symbol if it begins with "@@" + loadPropertyKey(mi, propertyName); // setup flags mi.push(memInfo.getAttributes()); // setup getter method handle @@ -319,6 +322,7 @@ public class ClassGenerator { javaName = SETTER_PREFIX + memInfo.getJavaName(); mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, setterDesc(memInfo))); } + // property = AccessorProperty.create(key, flags, getter, setter); mi.invokeStatic(ACCESSORPROPERTY_TYPE, ACCESSORPROPERTY_CREATE, ACCESSORPROPERTY_CREATE_DESC); // boolean Collection.add(property) mi.invokeInterface(COLLECTION_TYPE, COLLECTION_ADD, COLLECTION_ADD_DESC); @@ -333,8 +337,8 @@ public class ClassGenerator { // dup of Collection instance mi.dup(); - // property = AccessorProperty.create(key, flags, getter, setter); - mi.loadLiteral(propertyName); + // Load property name, converting to Symbol if it begins with "@@" + loadPropertyKey(mi, propertyName); // setup flags mi.push(getter.getAttributes()); // setup getter method handle @@ -347,6 +351,7 @@ public class ClassGenerator { mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, setter.getJavaName(), setter.getJavaDesc())); } + // property = AccessorProperty.create(key, flags, getter, setter); mi.invokeStatic(ACCESSORPROPERTY_TYPE, ACCESSORPROPERTY_CREATE, ACCESSORPROPERTY_CREATE_DESC); // boolean Collection.add(property) mi.invokeInterface(COLLECTION_TYPE, COLLECTION_ADD, COLLECTION_ADD_DESC); @@ -365,6 +370,22 @@ public class ClassGenerator { return getScriptClassInfo(new ClassReader(classBuf)); } + private static void loadFunctionName(final MethodGenerator mi, final String propertyName) { + if (propertyName.startsWith(SYMBOL_PREFIX)) { + mi.loadLiteral("Symbol[" + propertyName.substring(2) + "]"); + } else { + mi.loadLiteral(propertyName); + } + } + + private static void loadPropertyKey(final MethodGenerator mi, final String propertyName) { + if (propertyName.startsWith(SYMBOL_PREFIX)) { + mi.getStatic(NATIVESYMBOL_TYPE, propertyName.substring(2), SYMBOL_DESC); + } else { + mi.loadLiteral(propertyName); + } + } + private static ScriptClassInfo getScriptClassInfo(final ClassReader reader) { final ScriptClassInfoCollector scic = new ScriptClassInfoCollector(); reader.accept(scic, 0); diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java index 68baa214fe0..388ab9a294d 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java @@ -28,6 +28,8 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DES import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_SYMBOL; + import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.nashorn.internal.objects.annotations.Where; @@ -466,11 +468,10 @@ public final class MemberInfo implements Cloneable { switch (type.getSort()) { case Type.BOOLEAN: case Type.INT: - case Type.LONG: case Type.DOUBLE: return true; default: - return false; + return type != TYPE_SYMBOL; } } diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java index c233b82581a..233b4f95dfd 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java @@ -31,12 +31,14 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import jdk.internal.org.objectweb.asm.Type; +import jdk.nashorn.internal.objects.NativeSymbol; import jdk.nashorn.internal.runtime.AccessorProperty; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.PrototypeObject; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Specialization; +import jdk.nashorn.internal.runtime.Symbol; /** * String constants used for code generation/instrumentation. @@ -88,6 +90,8 @@ public interface StringConstants { static final Type TYPE_PROTOTYPEOBJECT = Type.getType(PrototypeObject.class); static final Type TYPE_SCRIPTFUNCTION = Type.getType(ScriptFunction.class); static final Type TYPE_SCRIPTOBJECT = Type.getType(ScriptObject.class); + static final Type TYPE_NATIVESYMBOL = Type.getType(NativeSymbol.class); + static final Type TYPE_SYMBOL = Type.getType(Symbol.class); static final String PROTOTYPE_SUFFIX = "$Prototype"; static final String CONSTRUCTOR_SUFFIX = "$Constructor"; @@ -101,7 +105,7 @@ public interface StringConstants { static final String ACCESSORPROPERTY_TYPE = TYPE_ACCESSORPROPERTY.getInternalName(); static final String ACCESSORPROPERTY_CREATE = "create"; static final String ACCESSORPROPERTY_CREATE_DESC = - Type.getMethodDescriptor(TYPE_ACCESSORPROPERTY, TYPE_STRING, Type.INT_TYPE, TYPE_METHODHANDLE, TYPE_METHODHANDLE); + Type.getMethodDescriptor(TYPE_ACCESSORPROPERTY, TYPE_OBJECT, Type.INT_TYPE, TYPE_METHODHANDLE, TYPE_METHODHANDLE); // PropertyMap static final String PROPERTYMAP_TYPE = TYPE_PROPERTYMAP.getInternalName(); @@ -143,4 +147,9 @@ public interface StringConstants { // ScriptObject.getClassName() method. static final String GET_CLASS_NAME = "getClassName"; static final String GET_CLASS_NAME_DESC = Type.getMethodDescriptor(TYPE_STRING); + + // NativeSymbol + static final String NATIVESYMBOL_TYPE = TYPE_NATIVESYMBOL.getInternalName(); + static final String SYMBOL_DESC = TYPE_SYMBOL.getDescriptor(); + static final String SYMBOL_PREFIX = "@@"; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/AbstractIterator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/AbstractIterator.java new file mode 100644 index 00000000000..b9af3032c29 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/AbstractIterator.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import java.lang.invoke.MethodHandle; +import java.util.function.Consumer; +import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.linker.Bootstrap; +import jdk.nashorn.internal.runtime.linker.InvokeByName; +import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +/** + * ECMA6 25.1.2 The %IteratorPrototype% Object + */ +@ScriptClass("Iterator") +public abstract class AbstractIterator extends ScriptObject { + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private final static Object ITERATOR_INVOKER_KEY = new Object(); + private final static Object NEXT_INVOKER_KEY = new Object(); + private final static Object DONE_INVOKER_KEY = new Object(); + private final static Object VALUE_INVOKER_KEY = new Object(); + + /** ECMA6 iteration kinds */ + enum IterationKind { + /** key iteration */ + KEY, + /** value iteration */ + VALUE, + /** key+value iteration */ + KEY_VALUE + } + + /** + * Create an abstract iterator object with the given prototype and property map. + * + * @param prototype the prototype + * @param map the property map + */ + protected AbstractIterator(final ScriptObject prototype, final PropertyMap map) { + super(prototype, map); + } + + /** + * 25.1.2.1 %IteratorPrototype% [ @@iterator ] ( ) + * + * @param self the self object + * @return this iterator + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator") + public static Object getIterator(final Object self) { + return self; + } + + @Override + public String getClassName() { + return "Iterator"; + } + + /** + * ES6 25.1.1.2 The Iterator Interface + * + * @param arg argument + * @return next iterator result + */ + protected abstract IteratorResult next(final Object arg); + + /** + * ES6 25.1.1.3 The IteratorResult Interface + * + * @param value result value + * @param done result status + * @param global the global object + * @return result object + */ + protected IteratorResult makeResult(final Object value, final Boolean done, final Global global) { + return new IteratorResult(value, done, global); + } + + /** + * ES6 7.4.1 GetIterator abstract operation + * + * @param iterable an object + * @param global the global object + * @return the iterator + */ + public static Object getIterator(final Object iterable, final Global global) { + final Object object = Global.toObject(iterable); + + if (object instanceof ScriptObject) { + // TODO we need to implement fast property access for Symbol keys in order to use InvokeByName here. + final Object getter = ((ScriptObject) object).get(NativeSymbol.iterator); + + if (Bootstrap.isCallable(getter)) { + try { + final MethodHandle invoker = global.getDynamicInvoker(ITERATOR_INVOKER_KEY, + () -> Bootstrap.createDynamicCallInvoker(Object.class, Object.class, Object.class)); + + final Object value = invoker.invokeExact(getter, iterable); + if (JSType.isPrimitive(value)) { + throw typeError("not.an.object", ScriptRuntime.safeToString(value)); + } + return value; + + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + throw typeError("not.a.function", ScriptRuntime.safeToString(getter)); + } + + throw typeError("cannot.get.iterator", ScriptRuntime.safeToString(iterable)); + } + + /** + * Iterate over an iterable object, passing every value to {@code consumer}. + * + * @param iterable an iterable object + * @param global the current global + * @param consumer the value consumer + */ + public static void iterate(final Object iterable, final Global global, final Consumer consumer) { + + final Object iterator = AbstractIterator.getIterator(Global.toObject(iterable), global); + + final InvokeByName nextInvoker = global.getInvokeByName(AbstractIterator.NEXT_INVOKER_KEY, + () -> new InvokeByName("next", Object.class, Object.class, Object.class)); + final MethodHandle doneInvoker = global.getDynamicInvoker(AbstractIterator.DONE_INVOKER_KEY, + () -> Bootstrap.createDynamicInvoker("done", NashornCallSiteDescriptor.GET_PROPERTY, Object.class, Object.class)); + final MethodHandle valueInvoker = global.getDynamicInvoker(AbstractIterator.VALUE_INVOKER_KEY, + () -> Bootstrap.createDynamicInvoker("value", NashornCallSiteDescriptor.GET_PROPERTY, Object.class, Object.class)); + + try { + do { + final Object next = nextInvoker.getGetter().invokeExact(iterator); + if (!Bootstrap.isCallable(next)) { + break; + } + + final Object result = nextInvoker.getInvoker().invokeExact(next, iterator, (Object) null); + if (!(result instanceof ScriptObject)) { + break; + } + + final Object done = doneInvoker.invokeExact(result); + if (JSType.toBoolean(done)) { + break; + } + + consumer.accept(valueInvoker.invokeExact(result)); + + } while (true); + + } catch (final RuntimeException r) { + throw r; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + + } +} + + diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java new file mode 100644 index 00000000000..6b890db3f24 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +@ScriptClass("ArrayIterator") +public class ArrayIterator extends AbstractIterator { + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private ScriptObject iteratedObject; + private long nextIndex = 0L; + private final IterationKind iterationKind; + private final Global global; + + + ArrayIterator(final Object iteratedObject, final IterationKind iterationKind, final Global global) { + super(global.getArrayIteratorPrototype(), $nasgenmap$); + this.iteratedObject = iteratedObject instanceof ScriptObject ? (ScriptObject) iteratedObject : null; + this.iterationKind = iterationKind; + this.global = global; + } + + /** + * 22.1.5.2.1 %ArrayIteratorPrototype%.next() + * + * @param self the self reference + * @param arg the argument + * @return the next result + */ + @Function + public static Object next(final Object self, final Object arg) { + if (!(self instanceof ArrayIterator)) { + throw typeError("not.a.array.iterator", ScriptRuntime.safeToString(self)); + } + return ((ArrayIterator)self).next(arg); + } + + @Override + public String getClassName() { + return "Array Iterator"; + } + + @Override + protected IteratorResult next(final Object arg) { + final long index = nextIndex; + + if (iteratedObject == null || index >= JSType.toUint32(iteratedObject.getLength())) { + // ES6 22.1.5.2.1 step 10 + iteratedObject = null; + return makeResult(Undefined.getUndefined(), Boolean.TRUE, global); + } + + nextIndex++; + + if (iterationKind == IterationKind.KEY_VALUE) { + final NativeArray value = new NativeArray( + new Object[] {JSType.toNarrowestNumber(index), iteratedObject.get((double) index)}); + return makeResult(value, Boolean.FALSE, global); + } + + final Object value = iterationKind == IterationKind.KEY ? + JSType.toNarrowestNumber(index) : iteratedObject.get((double) index); + return makeResult(value, Boolean.FALSE, global); + } + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java index 0f7209b181e..db042890cd7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java @@ -95,6 +95,8 @@ public final class Global extends Scope { // (__FILE__, __DIR__, __LINE__) private static final Object LAZY_SENTINEL = new Object(); + private static final String PACKAGE_PREFIX = "jdk.nashorn.internal.objects."; + private InvokeByName TO_STRING; private InvokeByName VALUE_OF; @@ -222,9 +224,6 @@ public final class Global extends Scope { @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE) public volatile Object number; - /** ECMA 2016 19.4.1 - Symbol constructor */ - @Property(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE) - public volatile Object symbol; /** * Getter for ECMA 15.1.4.7 Date property @@ -748,6 +747,147 @@ public final class Global extends Scope { private volatile Object float64Array; + + /** + * Getter for the Symbol property. + * + * @param self self reference + * @return the value of the Symbol property + */ + @Getter(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE) + public static Object getSymbol(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.symbol == LAZY_SENTINEL) { + global.symbol = global.getBuiltinSymbol(); + } + return global.symbol; + } + + /** + * Setter for the Symbol property. + * + * @param self self reference + * @param value value of the Symbol property + */ + @Setter(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE) + public static void setSymbol(final Object self, final Object value) { + Global.instanceFrom(self).symbol = value; + } + + private volatile Object symbol; + + /** + * Getter for the Map property. + * + * @param self self reference + * @return the value of the Map property + */ + @Getter(name = "Map", attributes = Attribute.NOT_ENUMERABLE) + public static Object getMap(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.map == LAZY_SENTINEL) { + global.map = global.getBuiltinMap(); + } + return global.map; + } + + /** + * Setter for the Map property. + * + * @param self self reference + * @param value value of the Map property + */ + @Setter(name = "Map", attributes = Attribute.NOT_ENUMERABLE) + public static void setMap(final Object self, final Object value) { + Global.instanceFrom(self).map = value; + } + + private volatile Object map; + + /** + * Getter for the WeakMap property. + * + * @param self self reference + * @return the value of the WeakMap property + */ + @Getter(name = "WeakMap", attributes = Attribute.NOT_ENUMERABLE) + public static Object getWeakMap(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.weakMap == LAZY_SENTINEL) { + global.weakMap = global.getBuiltinWeakMap(); + } + return global.weakMap; + } + + /** + * Setter for the WeakMap property. + * + * @param self self reference + * @param value value of the WeakMap property + */ + @Setter(name = "WeakMap", attributes = Attribute.NOT_ENUMERABLE) + public static void setWeakMap(final Object self, final Object value) { + Global.instanceFrom(self).weakMap = value; + } + + private volatile Object weakMap; + + /** + * Getter for the Set property. + * + * @param self self reference + * @return the value of the Set property + */ + @Getter(name = "Set", attributes = Attribute.NOT_ENUMERABLE) + public static Object getSet(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.set == LAZY_SENTINEL) { + global.set = global.getBuiltinSet(); + } + return global.set; + } + + /** + * Setter for the Set property. + * + * @param self self reference + * @param value value of the Set property + */ + @Setter(name = "Set", attributes = Attribute.NOT_ENUMERABLE) + public static void setSet(final Object self, final Object value) { + Global.instanceFrom(self).set = value; + } + + private volatile Object set; + + /** + * Getter for the WeakSet property. + * + * @param self self reference + * @return the value of the WeakSet property + */ + @Getter(name = "WeakSet", attributes = Attribute.NOT_ENUMERABLE) + public static Object getWeakSet(final Object self) { + final Global global = Global.instanceFrom(self); + if (global.weakSet == LAZY_SENTINEL) { + global.weakSet = global.getBuiltinWeakSet(); + } + return global.weakSet; + } + + /** + * Setter for the WeakSet property. + * + * @param self self reference + * @param value value of the WeakSet property + */ + @Setter(name = "WeakSet", attributes = Attribute.NOT_ENUMERABLE) + public static void setWeakSet(final Object self, final Object value) { + Global.instanceFrom(self).weakSet = value; + } + + private volatile Object weakSet; + /** Nashorn extension: Java access - global.Packages */ @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) public volatile Object packages; @@ -907,6 +1047,15 @@ public final class Global extends Scope { private ScriptFunction builtinFloat32Array; private ScriptFunction builtinFloat64Array; private ScriptFunction builtinSymbol; + private ScriptFunction builtinMap; + private ScriptFunction builtinWeakMap; + private ScriptFunction builtinSet; + private ScriptFunction builtinWeakSet; + private ScriptObject builtinIteratorPrototype; + private ScriptObject builtinMapIteratorPrototype; + private ScriptObject builtinSetIteratorPrototype; + private ScriptObject builtinArrayIteratorPrototype; + private ScriptObject builtinStringIteratorPrototype; /* * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object @@ -1673,7 +1822,58 @@ public final class Global extends Scope { } ScriptObject getSymbolPrototype() { - return ScriptFunction.getPrototype(builtinSymbol); + return ScriptFunction.getPrototype(getBuiltinSymbol()); + } + + ScriptObject getMapPrototype() { + return ScriptFunction.getPrototype(getBuiltinMap()); + } + + ScriptObject getWeakMapPrototype() { + return ScriptFunction.getPrototype(getBuiltinWeakMap()); + } + + ScriptObject getSetPrototype() { + return ScriptFunction.getPrototype(getBuiltinSet()); + } + + ScriptObject getWeakSetPrototype() { + return ScriptFunction.getPrototype(getBuiltinWeakSet()); + } + + ScriptObject getIteratorPrototype() { + if (builtinIteratorPrototype == null) { + builtinIteratorPrototype = initPrototype("AbstractIterator", getObjectPrototype()); + } + return builtinIteratorPrototype; + } + + ScriptObject getMapIteratorPrototype() { + if (builtinMapIteratorPrototype == null) { + builtinMapIteratorPrototype = initPrototype("MapIterator", getIteratorPrototype()); + } + return builtinMapIteratorPrototype; + } + + ScriptObject getSetIteratorPrototype() { + if (builtinSetIteratorPrototype == null) { + builtinSetIteratorPrototype = initPrototype("SetIterator", getIteratorPrototype()); + } + return builtinSetIteratorPrototype; + } + + ScriptObject getArrayIteratorPrototype() { + if (builtinArrayIteratorPrototype == null) { + builtinArrayIteratorPrototype = initPrototype("ArrayIterator", getIteratorPrototype()); + } + return builtinArrayIteratorPrototype; + } + + ScriptObject getStringIteratorPrototype() { + if (builtinStringIteratorPrototype == null) { + builtinStringIteratorPrototype = initPrototype("StringIterator", getIteratorPrototype()); + } + return builtinStringIteratorPrototype; } private synchronized ScriptFunction getBuiltinArrayBuffer() { @@ -1916,6 +2116,41 @@ public final class Global extends Scope { return this.builtinURIError; } + private synchronized ScriptFunction getBuiltinSymbol() { + if (this.builtinSymbol == null) { + this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class); + } + return this.builtinSymbol; + } + + private synchronized ScriptFunction getBuiltinMap() { + if (this.builtinMap == null) { + this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class); + } + return this.builtinMap; + } + + private synchronized ScriptFunction getBuiltinWeakMap() { + if (this.builtinWeakMap == null) { + this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class); + } + return this.builtinWeakMap; + } + + private synchronized ScriptFunction getBuiltinSet() { + if (this.builtinSet == null) { + this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class); + } + return this.builtinSet; + } + + private synchronized ScriptFunction getBuiltinWeakSet() { + if (this.builtinWeakSet == null) { + this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class); + } + return this.builtinWeakSet; + } + @Override public String getClassName() { return "global"; @@ -2311,14 +2546,6 @@ public final class Global extends Scope { this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); - if (env._es6) { - this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class); - } else { - // We need to manually delete nasgen-generated properties we don't want - this.delete("Symbol", false); - this.builtinObject.delete("getOwnPropertySymbols", false); - } - // initialize String.prototype.length to 0 // add String.prototype.length final ScriptObject stringPrototype = getStringPrototype(); @@ -2328,6 +2555,25 @@ public final class Global extends Scope { final ScriptObject arrayPrototype = getArrayPrototype(); arrayPrototype.setIsArray(); + if (env._es6) { + this.symbol = LAZY_SENTINEL; + this.map = LAZY_SENTINEL; + this.weakMap = LAZY_SENTINEL; + this.set = LAZY_SENTINEL; + this.weakSet = LAZY_SENTINEL; + } else { + // We need to manually delete nasgen-generated properties we don't want + this.delete("Symbol", false); + this.delete("Map", false); + this.delete("WeakMap", false); + this.delete("Set", false); + this.delete("WeakSet", false); + builtinObject.delete("getOwnPropertySymbols", false); + arrayPrototype.delete("entries", false); + arrayPrototype.delete("keys", false); + arrayPrototype.delete("values", false); + } + // Error stuff initErrorObjects(); @@ -2522,7 +2768,6 @@ public final class Global extends Scope { this.string = this.builtinString; this.syntaxError = this.builtinSyntaxError; this.typeError = this.builtinTypeError; - this.symbol = this.builtinSymbol; } private void initDebug() { @@ -2558,7 +2803,7 @@ public final class Global extends Scope { private T initConstructor(final String name, final Class clazz) { try { // Assuming class name pattern for built-in JS constructors. - final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects."); + final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX); sb.append("Native"); sb.append(name); @@ -2586,6 +2831,22 @@ public final class Global extends Scope { } } + private ScriptObject initPrototype(final String name, final ScriptObject prototype) { + try { + // Assuming class name pattern for JS prototypes + final String className = PACKAGE_PREFIX + name + "$Prototype"; + + final Class funcClass = Class.forName(className); + final ScriptObject res = (ScriptObject) funcClass.newInstance(); + + res.setIsBuiltin(); + res.setInitialProto(prototype); + return res; + } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + private List extractBuiltinProperties(final String name, final ScriptObject func) { final List list = new ArrayList<>(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/IteratorResult.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/IteratorResult.java new file mode 100644 index 00000000000..33c85753e53 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/IteratorResult.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import jdk.nashorn.internal.objects.annotations.Property; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; + +@ScriptClass("IteratorResult") +public class IteratorResult extends ScriptObject { + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + IteratorResult(final Object value, final Boolean done, final Global global) { + super(global.getObjectPrototype(), $nasgenmap$); + this.value = value; + this.done = done; + } + + /** + * The result value property. + */ + @Property + public Object value; + + /** + * The result status property. + */ + @Property + public Object done; + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/LinkedMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/LinkedMap.java new file mode 100644 index 00000000000..917bf099956 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/LinkedMap.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import jdk.nashorn.internal.runtime.Undefined; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + *

A linked hash map used by the ES6 Map and Set objects. As required by the ECMA specification for these objects, + * this class allows arbitrary modifications to the base collection while being iterated over. However, note that + * such modifications are only safe from the same thread performing the iteration; the class is not thread-safe.

+ * + *

Deletions and additions that occur during iteration are reflected in the elements visited by the iterator + * (except for deletion of elements that have already been visited). In non-concurrent Java collections such as + * {@code java.util.LinkedHashMap} this would result in a {@link java.util.ConcurrentModificationException} + * being thrown.

+ * + *

This class is implemented using a {@link java.util.HashMap} as backing storage with doubly-linked + * list nodes as values.

+ * + * @see Map.prototype.forEach + * @see Set.prototype.forEach + */ +public class LinkedMap { + + // We use a plain hash map as our hash storage. + private final Map data = new HashMap<>(); + + // The head and tail of our doubly-linked list. We use the same node to represent both the head and the + // tail of the list, so the list is circular. This node is never unlinked and thus always remain alive. + private final Node head = new Node(); + + /** + * A node of a linked list that is used as value in our map. The linked list uses insertion order + * and allows fast iteration over its element even while the map is modified. + */ + static class Node { + private final Object key; + private final Object value; + + private volatile boolean alive = true; + private volatile Node prev; + private volatile Node next; + + /** + * Constructor for the list head. This creates an empty circular list. + */ + private Node() { + this(null, null); + this.next = this; + this.prev = this; + } + + /** + * Constructor for value nodes. + * + * @param key the key + * @param value the value + */ + private Node(final Object key, final Object value) { + this.key = key; + this.value = value; + } + + /** + * Get the node's key. + * @return the hash key + */ + public Object getKey() { + return key; + } + + /** + * Get the node's value. + * @return the value + */ + public Object getValue() { + return value; + } + } + + /** + * An iterator over the elements in the map. + */ + class LinkedMapIterator { + + private Node cursor; + + private LinkedMapIterator() { + this.cursor = head; + } + + /** + * Get the next node in this iteration. Changes in the underlying map are reflected in the iteration + * as required by the ES6 specification. Note that this method could return a deleted node if deletion + * occurred concurrently on another thread. + * + * @return the next node + */ + public Node next() { + + if (cursor != null) { + // If last node is not alive anymore (i.e. has been deleted) go back to the last live node + // and continue from there. This may be the list head, which always remains alive. + while (!cursor.alive) { + assert cursor != head; + cursor = cursor.prev; + } + + cursor = cursor.next; + + if (cursor == head) { + cursor = null; // We've come full circle to the end + } + } + + return cursor; + } + } + + /** + * Add a key-value pair to the map. + * @param key the key + * @param value the value + */ + public void set(final Object key, final Object value) { + final Node newNode = new Node(key, value); + final Node oldNode = data.put(key, newNode); + if (oldNode != null) { + unlink(oldNode); + } + link(newNode); + } + + /** + * Get the value associated with {@code key}. + * @param key the key + * @return the associated value, or {@code null} if {@code key} is not contained in the map + */ + public Object get(final Object key) { + final Node node = data.get(key); + return node == null ? Undefined.getUndefined() : node.getValue(); + } + + /** + * Returns {@code true} if {@code key} is contained in the map. + * @param key the key + * @return {@code true} if {@code key} is contained + */ + public boolean has(final Object key) { + return data.containsKey(key); + } + + /** + * Delete the node associated with {@code key} from the map. + * @param key the key + * @return {@code true} if {@code key} was contained in the map + */ + public boolean delete (final Object key) { + final Node node = data.remove(key); + if (node != null) { + unlink(node); + return true; + } + return false; + } + + /** + * Remove all key-value pairs from the map. + */ + public void clear() { + data.clear(); + for (Node node = head.next; node != head; node = node.next) { + node.alive = false; + } + head.next = head; + head.prev = head; + } + + /** + * Return the current number of key-value pairs in the map. + * @return the map size + */ + public int size() { + return data.size(); + } + + /** + * Get an iterator over the key-value pairs in the map. + * @return an iterator + */ + public LinkedMapIterator getIterator() { + return new LinkedMapIterator(); + } + + private void link(final Node newNode) { + // We always insert at the end (head == tail) + newNode.next = head; + newNode.prev = head.prev; + newNode.prev.next = newNode; + head.prev = newNode; + } + + private void unlink(final Node oldNode) { + // Note that we unlink references to the node being deleted, but keep the references from the deleted node. + // This is necessary to allow iterators to go back to the last live node in case the current node has been + // deleted. Also, the forward link of a deleted node may still be followed by an iterator and must not be null. + oldNode.prev.next = oldNode.next; + oldNode.next.prev = oldNode.prev; + oldNode.alive = false; + } + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/MapIterator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/MapIterator.java new file mode 100644 index 00000000000..549e5963ce3 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/MapIterator.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +/** + * ECMA6 23.1.5 Map Iterator Objects + */ +@ScriptClass("MapIterator") +public class MapIterator extends AbstractIterator { + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private LinkedMap.LinkedMapIterator iterator; + + private final IterationKind iterationKind; + + // Cached global needed for each iteration result + private final Global global; + + /** + * Constructor for Map iterators. + * @param map the map to iterate over + * @param iterationKind the iteration kind + * @param global the current global object + */ + MapIterator(final NativeMap map, final IterationKind iterationKind, final Global global) { + super(global.getMapIteratorPrototype(), $nasgenmap$); + this.iterator = map.getJavaMap().getIterator(); + this.iterationKind = iterationKind; + this.global = global; + } + + /** + * ES6 23.1.5.2.1 %MapIteratorPrototype%.next() + * + * @param self the self reference + * @param arg the argument + * @return the next result + */ + @Function + public static Object next(final Object self, final Object arg) { + if (!(self instanceof MapIterator)) { + throw typeError("not.a.map.iterator", ScriptRuntime.safeToString(self)); + } + return ((MapIterator)self).next(arg); + } + + @Override + public String getClassName() { + return "Map Iterator"; + } + + @Override + protected IteratorResult next(final Object arg) { + if (iterator == null) { + return makeResult(Undefined.getUndefined(), Boolean.TRUE, global); + } + + final LinkedMap.Node node = iterator.next(); + + if (node == null) { + iterator = null; + return makeResult(Undefined.getUndefined(), Boolean.TRUE, global); + } + + if (iterationKind == IterationKind.KEY_VALUE) { + final NativeArray array = new NativeArray(new Object[] {node.getKey(), node.getValue()}); + return makeResult(array, Boolean.FALSE, global); + } + + return makeResult(iterationKind == IterationKind.KEY ? node.getKey() : node.getValue(), Boolean.FALSE, global); + } + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java index 06b2b0f72e2..b2090dcca6b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java @@ -1717,6 +1717,50 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin return reduceInner(reverseArrayLikeIterator(self), self, args); } + /** + * ECMA6 22.1.3.4 Array.prototype.entries ( ) + * + * @param self the self reference + * @return an iterator over the array's entries + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object entries(final Object self) { + return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.KEY_VALUE, Global.instance()); + } + + /** + * ECMA6 22.1.3.13 Array.prototype.keys ( ) + * + * @param self the self reference + * @return an iterator over the array's keys + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object keys(final Object self) { + return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.KEY, Global.instance()); + } + + /** + * ECMA6 22.1.3.29 Array.prototype.values ( ) + * + * @param self the self reference + * @return an iterator over the array's values + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object values(final Object self) { + return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.VALUE, Global.instance()); + } + + /** + * 22.1.3.30 Array.prototype [ @@iterator ] ( ) + * + * @param self the self reference + * @return an iterator over the array's values + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator") + public static Object getIterator(final Object self) { + return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.VALUE, Global.instance()); + } + /** * Determine if Java bulk array operations may be used on the underlying * storage. This is possible only if the object's prototype chain is empty diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeMap.java new file mode 100644 index 00000000000..7c173f9c86c --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeMap.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import java.lang.invoke.MethodHandle; + +import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Constructor; +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.Getter; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.objects.annotations.Where; +import jdk.nashorn.internal.runtime.ConsString; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; +import jdk.nashorn.internal.runtime.linker.Bootstrap; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +/** + * This implements the ECMA6 Map object. + */ +@ScriptClass("Map") +public class NativeMap extends ScriptObject { + + // our underlying map + private final LinkedMap map = new LinkedMap(); + + // key for the forEach invoker callback + private final static Object FOREACH_INVOKER_KEY = new Object(); + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private NativeMap(final ScriptObject proto, final PropertyMap map) { + super(proto, map); + } + + /** + * ECMA6 23.1.1 The Map Constructor + * + * @param isNew is this called with the new operator? + * @param self self reference + * @param arg optional iterable argument + * @return a new Map instance + */ + @Constructor(arity = 0) + public static Object construct(final boolean isNew, final Object self, final Object arg) { + if (!isNew) { + throw typeError("constructor.requires.new", "Map"); + } + final Global global = Global.instance(); + final NativeMap map = new NativeMap(global.getMapPrototype(), $nasgenmap$); + populateMap(map.getJavaMap(), arg, global); + return map; + } + + /** + * ECMA6 23.1.3.1 Map.prototype.clear ( ) + * + * @param self the self reference + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static void clear(final Object self) { + getNativeMap(self).map.clear(); + } + + /** + * ECMA6 23.1.3.3 Map.prototype.delete ( key ) + * + * @param self the self reference + * @param key the key to delete + * @return true if the key was deleted + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean delete(final Object self, final Object key) { + return getNativeMap(self).map.delete(convertKey(key)); + } + + /** + * ECMA6 23.1.3.7 Map.prototype.has ( key ) + * + * @param self the self reference + * @param key the key + * @return true if key is contained + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean has(final Object self, final Object key) { + return getNativeMap(self).map.has(convertKey(key)); + } + + /** + * ECMA6 23.1.3.9 Map.prototype.set ( key , value ) + * + * @param self the self reference + * @param key the key + * @param value the value + * @return this Map object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object set(final Object self, final Object key, final Object value) { + getNativeMap(self).map.set(convertKey(key), value); + return self; + } + + /** + * ECMA6 23.1.3.6 Map.prototype.get ( key ) + * + * @param self the self reference + * @param key the key + * @return the associated value or undefined + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object get(final Object self, final Object key) { + return getNativeMap(self).map.get(convertKey(key)); + } + + /** + * ECMA6 23.1.3.10 get Map.prototype.size + * + * @param self the self reference + * @return the size of the map + */ + @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.IS_ACCESSOR, where = Where.PROTOTYPE) + public static int size(final Object self) { + return getNativeMap(self).map.size(); + } + + /** + * ECMA6 23.1.3.4 Map.prototype.entries ( ) + * + * @param self the self reference + * @return an iterator over the Map's entries + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object entries(final Object self) { + return new MapIterator(getNativeMap(self), AbstractIterator.IterationKind.KEY_VALUE, Global.instance()); + } + + /** + * ECMA6 23.1.3.8 Map.prototype.keys ( ) + * + * @param self the self reference + * @return an iterator over the Map's keys + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object keys(final Object self) { + return new MapIterator(getNativeMap(self), AbstractIterator.IterationKind.KEY, Global.instance()); + } + + /** + * ECMA6 23.1.3.11 Map.prototype.values ( ) + * + * @param self the self reference + * @return an iterator over the Map's values + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object values(final Object self) { + return new MapIterator(getNativeMap(self), AbstractIterator.IterationKind.VALUE, Global.instance()); + } + + /** + * ECMA6 23.1.3.12 Map.prototype [ @@iterator ]( ) + * + * @param self the self reference + * @return An iterator over the Map's entries + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator") + public static Object getIterator(final Object self) { + return new MapIterator(getNativeMap(self), AbstractIterator.IterationKind.KEY_VALUE, Global.instance()); + } + + /** + * + * @param self the self reference + * @param callbackFn the callback function + * @param thisArg optional this-object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) + public static void forEach(final Object self, final Object callbackFn, final Object thisArg) { + final NativeMap map = getNativeMap(self); + if (!Bootstrap.isCallable(callbackFn)) { + throw typeError("not.a.function", ScriptRuntime.safeToString(callbackFn)); + } + final MethodHandle invoker = Global.instance().getDynamicInvoker(FOREACH_INVOKER_KEY, + () -> Bootstrap.createDynamicCallInvoker(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class)); + + final LinkedMap.LinkedMapIterator iterator = map.getJavaMap().getIterator(); + for (;;) { + final LinkedMap.Node node = iterator.next(); + if (node == null) { + break; + } + + try { + final Object result = invoker.invokeExact(callbackFn, thisArg, node.getValue(), node.getKey(), self); + } catch (final RuntimeException | Error e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + } + + @Override + public String getClassName() { + return "Map"; + } + + static void populateMap(final LinkedMap map, final Object arg, final Global global) { + if (arg != null && arg != Undefined.getUndefined()) { + AbstractIterator.iterate(arg, global, value -> { + if (JSType.isPrimitive(value)) { + throw typeError(global, "not.an.object", ScriptRuntime.safeToString(value)); + } + if (value instanceof ScriptObject) { + final ScriptObject sobj = (ScriptObject) value; + map.set(convertKey(sobj.get(0)), sobj.get(1)); + } + }); + } + } + + /** + * Returns a canonicalized key object by converting numbers to their narrowest representation and + * ConsStrings to strings. Conversion of Double to Integer also takes care of converting -0 to 0 + * as required by step 6 of ECMA6 23.1.3.9. + * + * @param key a key + * @return the canonical key + */ + static Object convertKey(final Object key) { + if (key instanceof ConsString) { + return key.toString(); + } + if (key instanceof Double) { + final Double d = (Double) key; + if (JSType.isRepresentableAsInt(d.doubleValue())) { + return d.intValue(); + } + } + return key; + } + + /** + * Get the underlying Java map. + * @return the Java map + */ + LinkedMap getJavaMap() { + return map; + } + + private static NativeMap getNativeMap(final Object self) { + if (self instanceof NativeMap) { + return (NativeMap)self; + } else { + throw typeError("not.a.map", ScriptRuntime.safeToString(self)); + } + } + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSet.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSet.java new file mode 100644 index 00000000000..da3ebe12c66 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSet.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import java.lang.invoke.MethodHandle; +import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Constructor; +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.Getter; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.objects.annotations.Where; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; +import jdk.nashorn.internal.runtime.linker.Bootstrap; + +import static jdk.nashorn.internal.objects.NativeMap.convertKey; +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +/** + * This implements the ECMA6 Set object. + */ +@ScriptClass("Set") +public class NativeSet extends ScriptObject { + + // our set/map implementation + private final LinkedMap map = new LinkedMap(); + + // Invoker for the forEach callback + private final static Object FOREACH_INVOKER_KEY = new Object(); + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private NativeSet(final ScriptObject proto, final PropertyMap map) { + super(proto, map); + } + + /** + * ECMA6 23.1 Set constructor + * + * @param isNew whether the new operator used + * @param self self reference + * @param arg optional iterable argument + * @return a new Set object + */ + @Constructor(arity = 0) + public static Object construct(final boolean isNew, final Object self, final Object arg){ + if (!isNew) { + throw typeError("constructor.requires.new", "Set"); + } + final Global global = Global.instance(); + final NativeSet set = new NativeSet(global.getSetPrototype(), $nasgenmap$); + populateSet(set.getJavaMap(), arg, global); + return set; + } + + /** + * ECMA6 23.2.3.1 Set.prototype.add ( value ) + * + * @param self the self reference + * @param value the value to add + * @return this Set object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object add(final Object self, final Object value) { + getNativeSet(self).map.set(convertKey(value), null); + return self; + } + + /** + * ECMA6 23.2.3.7 Set.prototype.has ( value ) + * + * @param self the self reference + * @param value the value + * @return true if value is contained + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean has(final Object self, final Object value) { + return getNativeSet(self).map.has(convertKey(value)); + } + + /** + * ECMA6 23.2.3.2 Set.prototype.clear ( ) + * + * @param self the self reference + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static void clear(final Object self) { + getNativeSet(self).map.clear(); + } + + /** + * ECMA6 23.2.3.4 Set.prototype.delete ( value ) + * + * @param self the self reference + * @param value the value + * @return true if value was deleted + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean delete(final Object self, final Object value) { + return getNativeSet(self).map.delete(convertKey(value)); + } + + /** + * ECMA6 23.2.3.9 get Set.prototype.size + * + * @param self the self reference + * @return the number of contained values + */ + @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.IS_ACCESSOR, where = Where.PROTOTYPE) + public static int size(final Object self) { + return getNativeSet(self).map.size(); + } + + /** + * ECMA6 23.2.3.5 Set.prototype.entries ( ) + * + * @param self the self reference + * @return an iterator over the Set object's entries + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object entries(final Object self) { + return new SetIterator(getNativeSet(self), AbstractIterator.IterationKind.KEY_VALUE, Global.instance()); + } + + /** + * ECMA6 23.2.3.8 Set.prototype.keys ( ) + * + * @param self the self reference + * @return an iterator over the Set object's values + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object keys(final Object self) { + return new SetIterator(getNativeSet(self), AbstractIterator.IterationKind.KEY, Global.instance()); + } + + /** + * ECMA6 23.2.3.10 Set.prototype.values ( ) + * + * @param self the self reference + * @return an iterator over the Set object's values + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object values(final Object self) { + return new SetIterator(getNativeSet(self), AbstractIterator.IterationKind.VALUE, Global.instance()); + } + + /** + * ECMA6 23.2.3.11 Set.prototype [ @@iterator ] ( ) + * + * @param self the self reference + * @return an iterator over the Set object's values + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator") + public static Object getIterator(final Object self) { + return new SetIterator(getNativeSet(self), AbstractIterator.IterationKind.VALUE, Global.instance()); + } + + /** + * ECMA6 23.2.3.6 Set.prototype.forEach ( callbackfn [ , thisArg ] ) + * + * @param self the self reference + * @param callbackFn the callback function + * @param thisArg optional this object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) + public static void forEach(final Object self, final Object callbackFn, final Object thisArg) { + final NativeSet set = getNativeSet(self); + if (!Bootstrap.isCallable(callbackFn)) { + throw typeError("not.a.function", ScriptRuntime.safeToString(callbackFn)); + } + final MethodHandle invoker = Global.instance().getDynamicInvoker(FOREACH_INVOKER_KEY, + () -> Bootstrap.createDynamicCallInvoker(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class)); + + final LinkedMap.LinkedMapIterator iterator = set.getJavaMap().getIterator(); + for (;;) { + final LinkedMap.Node node = iterator.next(); + if (node == null) { + break; + } + + try { + final Object result = invoker.invokeExact(callbackFn, thisArg, node.getKey(), node.getKey(), self); + } catch (final RuntimeException | Error e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + } + + @Override + public String getClassName() { + return "Set"; + } + + static void populateSet(final LinkedMap map, final Object arg, final Global global) { + if (arg != null && arg != Undefined.getUndefined()) { + AbstractIterator.iterate(arg, global, value -> map.set(convertKey(value), null)); + } + } + + LinkedMap getJavaMap() { + return map; + } + + private static NativeSet getNativeSet(final Object self) { + if (self instanceof NativeSet) { + return (NativeSet) self; + } else { + throw typeError("not.a.set", ScriptRuntime.safeToString(self)); + } + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java index 0b7869b8844..33e087bde80 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java @@ -1227,6 +1227,17 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti return newObj ? newObj(str) : str; } + /** + * ECMA 6 21.1.3.27 String.prototype [ @@iterator ]( ) + * + * @param self self reference + * @return a string iterator + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator") + public static Object getIterator(final Object self) { + return new StringIterator(checkObjectToString(self), Global.instance()); + } + /** * Lookup the appropriate method for an invoke dynamic call. * diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSymbol.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSymbol.java index d2c316241b6..9128422d766 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSymbol.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeSymbol.java @@ -37,6 +37,8 @@ import jdk.nashorn.internal.WeakValueCache; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.Getter; +import jdk.nashorn.internal.objects.annotations.Property; import jdk.nashorn.internal.objects.annotations.ScriptClass; import jdk.nashorn.internal.objects.annotations.Where; import jdk.nashorn.internal.runtime.JSType; @@ -66,6 +68,12 @@ public final class NativeSymbol extends ScriptObject { /** See ES6 19.4.2.1 */ private static WeakValueCache globalSymbolRegistry = new WeakValueCache<>(); + /** + * ECMA 6 19.4.2.4 Symbol.iterator + */ + @Property(where = Where.CONSTRUCTOR, attributes = Attribute.NON_ENUMERABLE_CONSTANT, name = "iterator") + public static final Symbol iterator = new Symbol("Symbol.iterator"); + NativeSymbol(final Symbol symbol) { this(symbol, Global.instance()); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java new file mode 100644 index 00000000000..6e11734e20a --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakMap.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import java.util.Map; +import java.util.WeakHashMap; +import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Constructor; +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; +import static jdk.nashorn.internal.runtime.JSType.isPrimitive; + +/** + * This implements the ECMA6 WeakMap object. + */ +@ScriptClass("WeakMap") +public class NativeWeakMap extends ScriptObject { + + private final Map jmap = new WeakHashMap<>(); + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private NativeWeakMap(final ScriptObject proto, final PropertyMap map) { + super(proto, map); + } + + /** + * ECMA6 23.3.1 The WeakMap Constructor + * + * @param isNew whether the new operator used + * @param self self reference + * @param arg optional iterable argument + * @return a new WeakMap object + */ + @Constructor(arity = 0) + public static Object construct(final boolean isNew, final Object self, final Object arg) { + if (!isNew) { + throw typeError("constructor.requires.new", "WeakMap"); + } + final Global global = Global.instance(); + final NativeWeakMap weakMap = new NativeWeakMap(global.getWeakMapPrototype(), $nasgenmap$); + populateMap(weakMap.jmap, arg, global); + return weakMap; + } + + /** + * ECMA6 23.3.3.5 WeakMap.prototype.set ( key , value ) + * + * @param self the self reference + * @param key the key + * @param value the value + * @return this WeakMap object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object set(final Object self, final Object key, final Object value) { + final NativeWeakMap map = getMap(self); + map.jmap.put(checkKey(key), value); + return self; + } + + /** + * ECMA6 23.3.3.3 WeakMap.prototype.get ( key ) + * + * @param self the self reference + * @param key the key + * @return the associated value or undefined + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object get(final Object self, final Object key) { + final NativeWeakMap map = getMap(self); + if (isPrimitive(key)) { + return Undefined.getUndefined(); + } + return map.jmap.get(key); + } + + /** + * ECMA6 23.3.3.2 WeakMap.prototype.delete ( key ) + * + * @param self the self reference + * @param key the key to delete + * @return true if the key was deleted + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean delete(final Object self, final Object key) { + final Map map = getMap(self).jmap; + if (isPrimitive(key)) { + return false; + } + final boolean returnValue = map.containsKey(key); + map.remove(key); + return returnValue; + } + + /** + * ECMA6 23.3.3.4 WeakMap.prototype.has ( key ) + * + * @param self the self reference + * @param key the key + * @return true if key is contained + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean has(final Object self, final Object key) { + final NativeWeakMap map = getMap(self); + return !isPrimitive(key) && map.jmap.containsKey(key); + } + + @Override + public String getClassName() { + return "WeakMap"; + } + + /** + * Make sure {@code key} is not a JavaScript primitive value. + * + * @param key a key object + * @return the valid key + */ + static Object checkKey(final Object key) { + if (isPrimitive(key)) { + throw typeError("invalid.weak.key", ScriptRuntime.safeToString(key)); + } + return key; + } + + static void populateMap(final Map map, final Object arg, final Global global) { + // This method is similar to NativeMap.populateMap, but it uses a different + // map implementation and the checking/conversion of keys differs as well. + if (arg != null && arg != Undefined.getUndefined()) { + AbstractIterator.iterate(arg, global, value -> { + if (isPrimitive(value)) { + throw typeError(global, "not.an.object", ScriptRuntime.safeToString(value)); + } + if (value instanceof ScriptObject) { + final ScriptObject sobj = (ScriptObject) value; + map.put(checkKey(sobj.get(0)), sobj.get(1)); + } + }); + } + } + + private static NativeWeakMap getMap(final Object self) { + if (self instanceof NativeWeakMap) { + return (NativeWeakMap)self; + } else { + throw typeError("not.a.weak.map", ScriptRuntime.safeToString(self)); + } + } + +} + + diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java new file mode 100644 index 00000000000..19e5f1c8405 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeWeakSet.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import java.util.Map; +import java.util.WeakHashMap; +import jdk.nashorn.internal.objects.annotations.Attribute; +import jdk.nashorn.internal.objects.annotations.Constructor; +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; + +import static jdk.nashorn.internal.objects.NativeWeakMap.checkKey; +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; +import static jdk.nashorn.internal.runtime.JSType.isPrimitive; + +/** + * This implements the ECMA6 WeakSet object. + */ +@ScriptClass("WeakSet") +public class NativeWeakSet extends ScriptObject { + + private final Map map = new WeakHashMap<>(); + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private NativeWeakSet(final ScriptObject proto, final PropertyMap map) { + super(proto, map); + } + + /** + * ECMA6 23.3.1 The WeakSet Constructor + * + * @param isNew whether the new operator used + * @param self self reference + * @param arg optional iterable argument + * @return a new WeakSet object + */ + @Constructor(arity = 0) + public static Object construct(final boolean isNew, final Object self, final Object arg) { + if (!isNew) { + throw typeError("constructor.requires.new", "WeakSet"); + } + final Global global = Global.instance(); + final NativeWeakSet weakSet = new NativeWeakSet(global.getWeakSetPrototype(), $nasgenmap$); + populateWeakSet(weakSet.map, arg, global); + return weakSet; + } + + /** + * ECMA6 23.4.3.1 WeakSet.prototype.add ( value ) + * + * @param self the self reference + * @param value the value to add + * @return this Set object + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static Object add(final Object self, final Object value) { + final NativeWeakSet set = getSet(self); + set.map.put(checkKey(value), Boolean.TRUE); + return self; + } + + /** + * ECMA6 23.4.3.4 WeakSet.prototype.has ( value ) + * + * @param self the self reference + * @param value the value + * @return true if value is contained + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean has(final Object self, final Object value) { + final NativeWeakSet set = getSet(self); + return !isPrimitive(value) && set.map.containsKey(value); + } + + /** + * ECMA6 23.4.3.3 WeakSet.prototype.delete ( value ) + * + * @param self the self reference + * @param value the value + * @return true if value was deleted + */ + @Function(attributes = Attribute.NOT_ENUMERABLE) + public static boolean delete(final Object self, final Object value) { + final Map map = getSet(self).map; + if (isPrimitive(value)) { + return false; + } + final boolean returnValue = map.containsKey(value); + map.remove(value); + return returnValue; + } + + @Override + public String getClassName() { + return "WeakSet"; + } + + static void populateWeakSet(final Map set, final Object arg, final Global global) { + if (arg != null && arg != Undefined.getUndefined()) { + AbstractIterator.iterate(arg, global, value -> { + set.put(checkKey(value), Boolean.TRUE); + }); + } + } + + private static NativeWeakSet getSet(final Object self) { + if (self instanceof NativeWeakSet) { + return (NativeWeakSet) self; + } else { + throw typeError("not.a.weak.set", ScriptRuntime.safeToString(self)); + } + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/SetIterator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/SetIterator.java new file mode 100644 index 00000000000..ac504bc502f --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/SetIterator.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +/** + * ECMA6 23.2.5 Set Iterator Objects + */ +@ScriptClass("SetIterator") +public class SetIterator extends AbstractIterator { + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private LinkedMap.LinkedMapIterator iterator; + + private final IterationKind iterationKind; + + // Cached global needed for every iteration result + private final Global global; + + SetIterator(final NativeSet set, final IterationKind iterationKind, final Global global) { + super(global.getSetIteratorPrototype(), $nasgenmap$); + this.iterator = set.getJavaMap().getIterator(); + this.iterationKind = iterationKind; + this.global = global; + } + + /** + * ES6 23.2.5.2.1 %SetIteratorPrototype%.next() + * + * @param self the self reference + * @param arg the argument + * @return the next result + */ + @Function + public static Object next(final Object self, final Object arg) { + if (!(self instanceof SetIterator)) { + throw typeError("not.a.set.iterator", ScriptRuntime.safeToString(self)); + } + return ((SetIterator)self).next(arg); + } + + @Override + public String getClassName() { + return "Set Iterator"; + } + + @Override + protected IteratorResult next(final Object arg) { + if (iterator == null) { + return makeResult(Undefined.getUndefined(), Boolean.TRUE, global); + } + + final LinkedMap.Node node = iterator.next(); + + if (node == null) { + iterator = null; + return makeResult(Undefined.getUndefined(), Boolean.TRUE, global); + } + + if (iterationKind == IterationKind.KEY_VALUE) { + final NativeArray array = new NativeArray(new Object[] {node.getKey(), node.getKey()}); + return makeResult(array, Boolean.FALSE, global); + } + + return makeResult(node.getKey(), Boolean.FALSE, global); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/StringIterator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/StringIterator.java new file mode 100644 index 00000000000..2c3cf0bb439 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/StringIterator.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.objects; + +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.Undefined; + +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + +/** + * ECMA6 21.1.5 String Iterator Objects + */ +@ScriptClass("StringIterator") +public class StringIterator extends AbstractIterator { + + // initialized by nasgen + private static PropertyMap $nasgenmap$; + + private String iteratedString; + private int nextIndex = 0; + private final Global global; + + StringIterator(final String iteratedString, final Global global) { + super(global.getStringIteratorPrototype(), $nasgenmap$); + this.iteratedString = iteratedString; + this.global = global; + } + + /** + * ES6 21.1.5.2.1 %StringIteratorPrototype%.next() + * + * @param self the self reference + * @param arg the argument + * @return the next result + */ + @Function + public static Object next(final Object self, final Object arg) { + if (!(self instanceof StringIterator)) { + throw typeError("not.a.string.iterator", ScriptRuntime.safeToString(self)); + } + return ((StringIterator)self).next(arg); + } + + @Override + public String getClassName() { + return "String Iterator"; + } + + @Override + protected IteratorResult next(final Object arg) { + final int index = nextIndex; + final String string = iteratedString; + + if (string == null || index >= string.length()) { + // ES6 21.1.5.2.1 step 8 + iteratedString = null; + return makeResult(Undefined.getUndefined(), Boolean.TRUE, global); + } + + final char first = string.charAt(index); + if (first >= 0xd800 && first <= 0xdbff && index < string.length() - 1) { + final char second = string.charAt(index + 1); + if (second >= 0xdc00 && second <= 0xdfff) { + nextIndex += 2; + return makeResult(String.valueOf(new char[] {first, second}), Boolean.FALSE, global); + } + } + + nextIndex++; + return makeResult(String.valueOf(first), Boolean.FALSE, global); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Attribute.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Attribute.java index a6b6b1baab8..f14d2e3fefb 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Attribute.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Attribute.java @@ -31,21 +31,31 @@ package jdk.nashorn.internal.objects.annotations; */ public interface Attribute { - /** flag for non writable objects */ + /** Flag for non-writable properties */ public static final int NOT_WRITABLE = jdk.nashorn.internal.runtime.Property.NOT_WRITABLE; - /** flag for non enumerable objects */ + /** Flag for non-enumerable properties */ public static final int NOT_ENUMERABLE = jdk.nashorn.internal.runtime.Property.NOT_ENUMERABLE; - /** flag for non configurable objects */ + /** Flag for non-configurable properties */ public static final int NOT_CONFIGURABLE = jdk.nashorn.internal.runtime.Property.NOT_CONFIGURABLE; - /** read-only, non-configurable property */ + /** + * Flag for accessor (getter/setter) properties as opposed to data properties. + * + *

This allows nasgen-created properties to behave like user-accessors. it should only be used for + * properties that are explicitly specified as accessor properties in the ECMAScript specification + * such as Map.prototype.size in ES6, not value properties that happen to be implemented by getter/setter + * such as the "length" properties of String or Array objects.

+ */ + public static final int IS_ACCESSOR = jdk.nashorn.internal.runtime.Property.IS_ACCESSOR_PROPERTY; + + /** Read-only, non-configurable property */ public static final int CONSTANT = NOT_WRITABLE | NOT_CONFIGURABLE; - /** non-enumerable, read-only, non-configurable property */ + /** Non-enumerable, read-only, non-configurable property */ public static final int NON_ENUMERABLE_CONSTANT = NOT_ENUMERABLE | CONSTANT; - /** by default properties are writable, enumerable and configurable */ + /** By default properties are writable, enumerable and configurable */ public static final int DEFAULT_ATTRIBUTES = 0; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java index 05574d9602a..be5d052092c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java @@ -127,7 +127,7 @@ public class AccessorProperty extends Property { * * @return New {@link AccessorProperty} created. */ - public static AccessorProperty create(final String key, final int propertyFlags, final MethodHandle getter, final MethodHandle setter) { + public static AccessorProperty create(final Object key, final int propertyFlags, final MethodHandle getter, final MethodHandle setter) { return new AccessorProperty(key, propertyFlags, -1, getter, setter); } @@ -601,6 +601,11 @@ public class AccessorProperty extends Property { return getLocalType() == null; } + @Override + public boolean hasNativeSetter() { + return objectSetter != null; + } + @Override public MethodHandle getSetter(final Class type, final PropertyMap currentMap) { checkUndeclared(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java index fd17851d468..01c050bb3ff 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java @@ -163,7 +163,7 @@ public final class FindProperty { * @return appropriate receiver */ public ScriptObject getGetterReceiver() { - return property != null && property instanceof UserAccessorProperty ? self : prototype; + return property != null && property.isAccessorProperty() ? self : prototype; } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java index fc4df5d6b17..06463ab9d39 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java @@ -99,6 +99,9 @@ public abstract class Property implements Serializable { /** Does this property support dual field representation? */ public static final int DUAL_FIELDS = 1 << 11; + /** Is this an accessor property as as defined in ES5 8.6.1? */ + public static final int IS_ACCESSOR_PROPERTY = 1 << 12; + /** Property key. */ private final Object key; @@ -495,6 +498,16 @@ public abstract class Property implements Serializable { */ public abstract void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict); + /** + * Returns true if this property has a low-level setter handle. This can be used to determine whether a + * nasgen-generated accessor property should be treated as non-writable. For user-created accessor properties + * {@link #hasSetterFunction(ScriptObject)} should be used to find whether a setter function exists in + * a given object. + * + * @return true if a native setter handle exists + */ + public abstract boolean hasNativeSetter(); + /** * Abstract method for retrieving the setter for the property. We do not know * anything about the internal representation when we request the setter, we only @@ -693,4 +706,12 @@ public abstract class Property implements Serializable { public boolean hasDualFields() { return (flags & DUAL_FIELDS) != 0; } + + /** + * Is this an accessor property as defined in ES5 8.6.1? + * @return true if this is an accessor property + */ + public boolean isAccessorProperty() { + return (flags & IS_ACCESSOR_PROPERTY) != 0; + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java index 76711806b76..575e6415f3c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java @@ -702,10 +702,8 @@ public class PropertyMap implements Iterable, Serializable { private boolean allFrozen() { for (final Property property : properties.getProperties()) { // check if it is a data descriptor - if (!(property instanceof UserAccessorProperty)) { - if (property.isWritable()) { - return false; - } + if (!property.isAccessorProperty() && property.isWritable()) { + return false; } if (property.isConfigurable()) { return false; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java index 13a61c81c1c..d13e58bab54 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java @@ -612,7 +612,7 @@ public class ScriptFunction extends ScriptObject { * * @param newPrototype new prototype object */ - public synchronized final void setPrototype(final Object newPrototype) { + public final void setPrototype(final Object newPrototype) { if (newPrototype instanceof ScriptObject && newPrototype != this.prototype && allocatorMap != null) { // Unset allocator map to be replaced with one matching the new prototype. allocatorMap = null; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java index 709f2fec9ff..b5d1265b2ea 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java @@ -468,7 +468,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { final boolean enumerable = property.isEnumerable(); final boolean writable = property.isWritable(); - if (property instanceof UserAccessorProperty) { + if (property.isAccessorProperty()) { return global.newAccessorDescriptor( get != null ? get : @@ -910,10 +910,9 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { } private void erasePropertyValue(final Property property) { - // Erase the property field value with undefined. If the property is defined - // by user-defined accessors, we don't want to call the setter!! - if (!(property instanceof UserAccessorProperty)) { - assert property != null; + // Erase the property field value with undefined. If the property is an accessor property + // we don't want to call the setter!! + if (property != null && !property.isAccessorProperty()) { property.setValue(this, this, UNDEFINED, false); } } @@ -996,7 +995,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { assert gs != null; //reuse existing getter setter for speed gs.set(getter, setter); - if (uc.getFlags() == propertyFlags) { + if (uc.getFlags() == (propertyFlags | Property.IS_ACCESSOR_PROPERTY)) { return oldProperty; } newProperty = new UserAccessorProperty(uc.getKey(), propertyFlags, slot); @@ -2022,7 +2021,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { } else if (!find.isSelf()) { assert mh.type().returnType().equals(returnType) : "return type mismatch for getter " + mh.type().returnType() + " != " + returnType; - if (!(property instanceof UserAccessorProperty)) { + if (!property.isAccessorProperty()) { // Add a filter that replaces the self object with the prototype owning the property. mh = addProtoFilter(mh, find.getProtoChainLength()); } @@ -2185,7 +2184,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { FindProperty find = findProperty(name, true, this); // If it's not a scope search, then we don't want any inherited properties except those with user defined accessors. - if (find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { + if (find != null && find.isInherited() && !find.getProperty().isAccessorProperty()) { // We should still check if inherited data property is not writable if (isExtensible() && !find.getProperty().isWritable()) { return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true); @@ -2201,9 +2200,13 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { if (NashornCallSiteDescriptor.isScope(desc) && find.getProperty().isLexicalBinding()) { throw typeError("assign.constant", name); // Overwriting ES6 const should throw also in non-strict mode. } - // Existing, non-writable property + // Existing, non-writable data property return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true); } + if (!find.getProperty().hasNativeSetter()) { + // Existing accessor property without setter + return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.has.no.setter", true); + } } else { if (!isExtensible()) { return createEmptySetMethod(desc, explicitInstanceOfCheck, "object.non.extensible", false); @@ -3040,7 +3043,7 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { invalidateGlobalConstant(key); - if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) { + if (f != null && f.isInherited() && !f.getProperty().isAccessorProperty()) { final boolean isScope = isScopeFlag(callSiteFlags); // If the start object of the find is not this object it means the property was found inside a // 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set' @@ -3061,12 +3064,14 @@ public abstract class ScriptObject implements PropertyAccess, Cloneable { } if (f != null) { - if (!f.getProperty().isWritable()) { + if (!f.getProperty().isWritable() || !f.getProperty().hasNativeSetter()) { if (isScopeFlag(callSiteFlags) && f.getProperty().isLexicalBinding()) { throw typeError("assign.constant", key.toString()); // Overwriting ES6 const should throw also in non-strict mode. } if (isStrictFlag(callSiteFlags)) { - throw typeError("property.not.writable", key.toString(), ScriptRuntime.safeToString(this)); + throw typeError( + f.getProperty().isAccessorProperty() ? "property.has.no.setter" : "property.not.writable", + key.toString(), ScriptRuntime.safeToString(this)); } return; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java index d58fb92b810..2165d9b7867 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java @@ -54,7 +54,7 @@ final class SetMethodCreator { /** * Creates a new property setter method creator. * @param sobj the object for which we're creating the property setter - * @param find a result of a {@link ScriptObject#findProperty(String, boolean)} on the object for the property we + * @param find a result of a {@link ScriptObject#findProperty(Object, boolean)} on the object for the property we * want to create a setter for. Can be null if the property does not yet exist on the object. * @param desc the descriptor of the call site that triggered the property setter lookup * @param request the link request @@ -66,7 +66,6 @@ final class SetMethodCreator { this.desc = desc; this.type = desc.getMethodType().parameterType(1); this.request = request; - } private String getName() { @@ -172,7 +171,7 @@ final class SetMethodCreator { assert property != null; final MethodHandle boundHandle; - if (!(property instanceof UserAccessorProperty) && find.isInherited()) { + if (!property.isAccessorProperty() && find.isInherited()) { boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength()); } else { boundHandle = methodHandle; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java index 6dc0ab500a2..502e9dca85a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java @@ -119,7 +119,8 @@ public final class UserAccessorProperty extends SpillProperty { * @param slot spill slot */ UserAccessorProperty(final Object key, final int flags, final int slot) { - super(key, flags, slot); + // Always set accessor property flag for this class + super(key, flags | IS_ACCESSOR_PROPERTY, slot); } private UserAccessorProperty(final UserAccessorProperty property) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java index 222c58c4986..022c0f16d93 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java @@ -42,7 +42,6 @@ import jdk.nashorn.internal.runtime.GlobalConstants; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.UserAccessorProperty; /** * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and @@ -118,7 +117,7 @@ public final class PrimitiveLookup { return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null); } - if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { + if (find.isInherited() && !(find.getProperty().isAccessorProperty())) { // If property is found in the prototype object bind the method handle directly to // the proto filter instead of going through wrapper instantiation below. final ScriptObject proto = wrappedReceiver.getProto(); @@ -180,9 +179,13 @@ public final class PrimitiveLookup { // See ES5.1 8.7.2 PutValue (V, W) final String name = JSType.toString(key); final FindProperty find = wrappedSelf.findProperty(name, true); - if (find == null || !(find.getProperty() instanceof UserAccessorProperty) || !find.getProperty().isWritable()) { + if (find == null || !find.getProperty().isAccessorProperty() || !find.getProperty().hasNativeSetter()) { if (strict) { - throw typeError("property.not.writable", name, ScriptRuntime.safeToString(self)); + if (find == null || !find.getProperty().isAccessorProperty()) { + throw typeError("property.not.writable", name, ScriptRuntime.safeToString(self)); + } else { + throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self)); + } } return; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties index e1118e33c5c..7e7e3c30d6e 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -82,6 +82,14 @@ type.error.not.a.string={0} is not a String type.error.not.a.function={0} is not a function type.error.not.a.function.value={0}, which has value {1}, is not a function type.error.not.a.constructor={0} is not a constructor function +type.error.not.a.map={0} is not a Map object +type.error.not.a.set={0} is not a Set object +type.error.not.a.weak.map={0} is not a WeakMap object +type.error.not.a.weak.set={0} is not a WeakSet object +type.error.not.a.map.iterator={0} is not a Map iterator +type.error.not.a.set.iterator={0} is not a Set iterator +type.error.not.a.array.iterator={0} is not an Array iterator +type.error.not.a.string.iterator={0} is not a String iterator type.error.not.a.file={0} is not a File type.error.not.a.numeric.array={0} is not a numeric array type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer @@ -122,6 +130,7 @@ type.error.array.reduceright.invalid.init=invalid initialValue for Array.prototy type.error.assign.constant=Assignment to constant "{0}" type.error.cannot.get.default.string=Cannot get default string value type.error.cannot.get.default.number=Cannot get default number value +type.error.cannot.get.iterator=Cannot get iterator from {1} type.error.cant.apply.with.to.null=Cannot apply "with" to null type.error.cant.apply.with.to.undefined=Cannot apply "with" to undefined type.error.cant.apply.with.to.non.scriptobject=Cannot apply "with" to non script object. Consider using "with(Object.bindProperties('{'}, nonScriptObject))". @@ -154,7 +163,7 @@ type.error.unsupported.java.to.type=Unsupported Java.to target type {0}. type.error.java.array.conversion.failed=Java.to conversion to array type {0} failed type.error.constructor.requires.new=Constructor {0} requires "new". type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}. -type.error.invalid.weak.key=invalid value {0} used as weak key. +type.error.invalid.weak.key=primitive value {0} used as weak key. type.error.symbol.to.string=Can not convert Symbol value to string. type.error.symbol.to.number=Can not convert Symbol value to number. type.error.not.a.symbol={0} is not a symbol. diff --git a/nashorn/test/script/basic/es6.js b/nashorn/test/script/basic/es6.js index 24ad1c8b54d..1b97fd33f6f 100644 --- a/nashorn/test/script/basic/es6.js +++ b/nashorn/test/script/basic/es6.js @@ -28,13 +28,21 @@ * @run */ -if (typeof Symbol !== 'undefined' || 'Symbol' in this) { - Assert.fail('Symbol is defined in global scope'); +function checkUndefined(name, object) { + if (typeof object[name] !== 'undefined' || name in object) { + Assert.fail(name + ' is defined in ' + object); + } } -if (typeof Object.getOwnPropertySymbols !== 'undefined' || 'getOwnPropertySymbols' in Object) { - Assert.fail('getOwnPropertySymbols is defined in global Object'); -} +checkUndefined('Symbol', this); +checkUndefined('Map', this); +checkUndefined('Set', this); +checkUndefined('WeakMap', this); +checkUndefined('WeakSet', this); +checkUndefined('getOwnPropertySymbols', Object); +checkUndefined('entries', Array.prototype); +checkUndefined('values', Array.prototype); +checkUndefined('keys', Array.prototype); function expectError(src, msg, error) { try { diff --git a/nashorn/test/script/basic/es6/iterator.js b/nashorn/test/script/basic/es6/iterator.js new file mode 100644 index 00000000000..060573013dd --- /dev/null +++ b/nashorn/test/script/basic/es6/iterator.js @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * JDK-8147558: Add support for ES6 collections + * + * @test + * @run + * @option --language=es6 + */ + + +function testIterator(iter, expectedValues) { + let next; + + for (var i = 0; i < expectedValues.length; i++) { + next = iter.next(); + Assert.assertTrue(next.done === false); + + if (Array.isArray(expectedValues[i])) { + Assert.assertTrue(Array.isArray(next.value)); + Assert.assertTrue(next.value.length === expectedValues[i].length); + Assert.assertTrue(next.value.every(function(v, j) { + return v === expectedValues[i][j]; + })); + + } else { + Assert.assertTrue(next.value === expectedValues[i]); + } + } + + next = iter.next(); + Assert.assertTrue(next.done === true); + Assert.assertTrue(next.value === undefined); +} + +const str = "abcdefg"; +const array = ["a", "b", "c", "d", "e", "f", "g"]; +const arrayKeys = [0, 1, 2, 3, 4, 5, 6]; +const setEntries = [["a", "a"], ["b", "b"], ["c", "c"], ["d", "d"], ["e", "e"], ["f", "f"], ["g", "g"]]; +const mapEntries = [["a", "A"], ["b", "B"], ["c", "C"], ["d", "D"], ["e", "E"], ["f", "F"], ["g", "G"]]; +const mapValues = ["A", "B", "C", "D", "E", "F", "G"]; +const arrayEntries = [[0, "a"], [1, "b"], [2, "c"], [3, "d"], [4, "e"], [5, "f"], [6, "g"]]; + +// Set iterator tests +const set = new Set(str); +testIterator(set[Symbol.iterator](), str); +testIterator(set.values(), str); +testIterator(set.keys(), str); +testIterator(set.entries(), setEntries); + +// Map iterator tests +const map = new Map(mapEntries); +testIterator(map[Symbol.iterator](), mapEntries); +testIterator(map.values(), mapValues); +testIterator(map.keys(), array); +testIterator(map.entries(), mapEntries); + +// String iterator tests +testIterator(str[Symbol.iterator](), str); + +// Array iterator tests +testIterator(array[Symbol.iterator](), array); +testIterator(array.values(), array); +testIterator(array.keys(), arrayKeys); +testIterator(array.entries(), arrayEntries); + diff --git a/nashorn/test/script/basic/es6/map.js b/nashorn/test/script/basic/es6/map.js new file mode 100644 index 00000000000..a1694593b46 --- /dev/null +++ b/nashorn/test/script/basic/es6/map.js @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * JDK-8147558: Add support for ES6 collections + * + * @test + * @run + * @option --language=es6 + */ + +function assertThrows(src, error) { + try { + eval(src); + Assert.fail("No error, expected " + error); + } catch (e) { + if (!(e instanceof error)) { + Assert.fail("Wrong error, expected " + error + " but got " + e); + } + } +} + +// Map constructor and prototype + +var desc = Object.getOwnPropertyDescriptor(this, "Map"); +Assert.assertEquals(desc.writable, true); +Assert.assertEquals(desc.configurable, true); +Assert.assertEquals(desc.enumerable, false); + +Assert.assertTrue(Object.getPrototypeOf(new Map()) === Map.prototype); +Assert.assertTrue(Object.getPrototypeOf(Map.prototype) === Object.prototype); +Assert.assertTrue(new Map().size === 0); +Assert.assertTrue(Object.getPrototypeOf(new Map([["a", 1], ["b", 2]])) === Map.prototype); +Assert.assertTrue(new Map([["a", 1], ["b", 2]]).size === 2); +Assert.assertTrue(Object.getPrototypeOf(new Map("")) === Map.prototype); +Assert.assertTrue(new Map("").size === 0); +Assert.assertTrue(Object.getPrototypeOf(new Map([])) === Map.prototype); +Assert.assertTrue(new Map([]).size === 0); + +assertThrows("Map()", TypeError); +assertThrows("new Map(3)", TypeError); +assertThrows("new Map('abc')", TypeError); +assertThrows("new Map({})", TypeError); +assertThrows("new Map([1, 2, 3])", TypeError); + +assertThrows("Map.prototype.set.apply({}, ['', ''])", TypeError); +assertThrows("Map.prototype.get.apply([], [''])", TypeError); +assertThrows("Map.prototype.has.apply(3, [''])", TypeError); +assertThrows("Map.prototype.clear.apply('', [])", TypeError); + +// Map methods + +var m = new Map([["a", 1], ["b", 2]]); +Assert.assertTrue(m.size, 2); +Assert.assertTrue(m.get("a") === 1); +Assert.assertTrue(m.get("b") === 2); +Assert.assertTrue(m.get("c") === undefined); +Assert.assertTrue(m.has("a") === true); +Assert.assertTrue(m.has("b") === true); +Assert.assertTrue(m.has("c") === false); + +m.clear(); +Assert.assertTrue(m.size === 0); +Assert.assertTrue(m.get("a") === undefined); +Assert.assertTrue(m.get("b") === undefined); +Assert.assertTrue(m.get("c") === undefined); +Assert.assertTrue(m.has("a") === false); +Assert.assertTrue(m.has("b") === false); +Assert.assertTrue(m.has("c") === false); + +var a = "a", x = "x"; // for ConsString keys +Assert.assertTrue(m.set("ab", false) === m); +Assert.assertTrue(m.set(x + "y", m) === m); +Assert.assertTrue(m.get(a + "b") === false); +Assert.assertTrue(m.get("xy") === m); +Assert.assertTrue(m.has(a + "b") === true); +Assert.assertTrue(m.has("xy") === true); + +// Special keys + +m = new Map(); +Assert.assertTrue(m.set(NaN, NaN) === m); // NaN should work as key +Assert.assertTrue(m.size === 1); +Assert.assertTrue(isNaN(m.get(NaN))); +Assert.assertTrue(isNaN(m.keys().next().value)); +Assert.assertTrue(isNaN(m.values().next().value)); +Assert.assertTrue(m.has(NaN) === true); +Assert.assertTrue(m.delete(NaN)); +Assert.assertTrue(m.size === 0); +Assert.assertTrue(m.get(NaN) === undefined); +Assert.assertTrue(m.keys().next().done); +Assert.assertTrue(m.values().next().done); +Assert.assertTrue(m.has(NaN) === false); + +m.clear(); +m.set(-0, -0); // -0 key should be converted to +0 +Assert.assertTrue(m.size === 1); +Assert.assertTrue(m.get(-0) === 0); +Assert.assertTrue(1 / m.keys().next().value === Infinity); +Assert.assertTrue(1 / m.values().next().value === -Infinity); +Assert.assertTrue(m.has(-0) === true); +Assert.assertTrue(m.has(0) === true); +Assert.assertTrue(m.delete(-0)); +Assert.assertTrue(m.size === 0); +Assert.assertTrue(m.get(-0) === undefined); +Assert.assertTrue(m.get(0) === undefined); +Assert.assertTrue(m.has(-0) === false); +Assert.assertTrue(m.has(0) === false); + +Assert.assertFalse(m.delete("foo")); +Assert.assertFalse(m.delete(0)); +Assert.assertFalse(m.delete(NaN)); + +// foreach + +m = new Map([[1, "one"], [2, "two"], [3, "three"]]); +m.forEach(function(value, key, map) { + Assert.assertTrue(this === m); + Assert.assertTrue(map === m); +}, m); + +function assertEqualArrays(a, b) { + Assert.assertTrue(Array.isArray(a)); + Assert.assertTrue(Array.isArray(b)); + Assert.assertTrue(a.length === b.length); + Assert.assertTrue(a.every(function(v, j) { + return v === b[j]; + })); +} + +let array = []; +m = new Map([[1, "one"], [2, "two"], [3, "three"]]); +m.forEach(function(value, key, map) { + array.push(value); +}); +assertEqualArrays(array, ["one", "two", "three"]); + +array = []; +m = new Map([[1, "one"], [2, "two"], [3, "three"]]); +m.forEach(function(value, key, map) { + array.push(value); + if (key == 3) { + map.clear(); + map.set(4, "four"); + } +}); +assertEqualArrays(array, ["one", "two", "three", "four"]); + +array = []; +m = new Map([[1, "one"], [2, "two"], [3, "three"]]); +m.forEach(function(value, key, map) { + array.push(value); + if (key == 1) { + map.delete(1); + } + if (key == 2) { + map.delete(3); + } +}); +assertEqualArrays(array, ["one", "two"]); + +array = []; +m = new Map([[1, "one"], [2, "two"], [3, "three"]]); +m.forEach(function(value, key, map) { + array.push(value); + if (array.length < 4) { + map.delete(key); + map.set(key, key + 3) + } +}); +assertEqualArrays(array, ["one", "two", "three", 4, 5, 6]); + + + + diff --git a/nashorn/test/script/basic/es6/set.js b/nashorn/test/script/basic/es6/set.js new file mode 100644 index 00000000000..3a37bf09b23 --- /dev/null +++ b/nashorn/test/script/basic/es6/set.js @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * JDK-8147558: Add support for ES6 collections + * + * @test + * @run + * @option --language=es6 + */ + +function assertThrows(src, error) { + try { + eval(src); + Assert.fail("No error, expected " + error); + } catch (e) { + if (!(e instanceof error)) { + Assert.fail("Wrong error, expected " + error + " but got " + e); + } + } +} + +// Set constructor and prototype + +var desc = Object.getOwnPropertyDescriptor(this, "Set"); +Assert.assertEquals(desc.writable, true); +Assert.assertEquals(desc.configurable, true); +Assert.assertEquals(desc.enumerable, false); + +Assert.assertTrue(Object.getPrototypeOf(new Set()) === Set.prototype); +Assert.assertTrue(Object.getPrototypeOf(Set.prototype) === Object.prototype); +Assert.assertTrue(new Set().size === 0); +Assert.assertTrue(Object.getPrototypeOf(new Set(["a", 3, false])) === Set.prototype); +Assert.assertTrue(new Set(["a", 3, false]).size === 3); +Assert.assertTrue(new Set("abc").size === 3); +Assert.assertTrue(new Set("").size === 0); +Assert.assertTrue(new Set([]).size === 0); + +assertThrows("Set()", TypeError); +assertThrows("new Set(3)", TypeError); +assertThrows("new Set({})", TypeError); + +assertThrows("Set.prototype.add.apply({}, [''])", TypeError); +assertThrows("Set.prototype.has.apply(3, [''])", TypeError); +assertThrows("Set.prototype.delete.apply('', [3])", TypeError); + +// Set methods + +var s = new Set(["a", 3, false]); +Assert.assertTrue(s.size, 2); +Assert.assertTrue(s.has("a") === true); +Assert.assertTrue(s.has(3) === true); +Assert.assertTrue(s.has(false) === true); + +Assert.assertTrue(s.clear() === undefined); +Assert.assertTrue(s.size === 0); +Assert.assertTrue(s.has("a") === false); +Assert.assertTrue(s.has(3) === false); +Assert.assertTrue(s.has(false) === false); + +var a = "a", x = "x"; // for ConsString keys +Assert.assertTrue(s.add("ab", false) === s); +Assert.assertTrue(s.add(x + "y", s) === s); +Assert.assertTrue(s.has(a + "b") === true); +Assert.assertTrue(s.has("xy") === true); + +// Special keys + +s.clear() +Assert.assertTrue(s.add(NaN) === s); // NaN should work as key +Assert.assertTrue(s.size === 1); +Assert.assertTrue(isNaN(s.keys().next().value)); +Assert.assertTrue(isNaN(s.values().next().value)); +Assert.assertTrue(s.has(NaN) === true); +Assert.assertTrue(s.delete(NaN) === true); +Assert.assertTrue(s.size === 0); +Assert.assertTrue(s.keys().next().done); +Assert.assertTrue(s.values().next().done); +Assert.assertTrue(s.has(NaN) === false); + +s.clear() +s.add(-0); // -0 key should be converted to +0 +Assert.assertTrue(s.size === 1); +Assert.assertTrue(1 / s.keys().next().value === Infinity); +Assert.assertTrue(1 / s.values().next().value === Infinity); +Assert.assertTrue(s.has(-0) === true); +Assert.assertTrue(s.has(0) === true); +Assert.assertTrue(s.delete(-0) === true); +Assert.assertTrue(s.size === 0); +Assert.assertTrue(s.has(-0) === false); +Assert.assertTrue(s.has(0) === false); + +// foreach + +s = new Set([1, 2, 3]); + +s.forEach(function(value, key, set) { + Assert.assertTrue(this === s); + Assert.assertTrue(set === s); +}, s); + +function assertEqualArrays(a, b) { + Assert.assertTrue(Array.isArray(a)); + Assert.assertTrue(Array.isArray(b)); + Assert.assertTrue(a.length === b.length); + Assert.assertTrue(a.every(function(v, j) { + return v === b[j]; + })); +} + +let array = []; +s = new Set([1, 2, 3]); +s.forEach(function(value, key, set) { + array.push(value); +}); +assertEqualArrays(array, [1, 2, 3]); + +array = []; +s = new Set([1, 2, 3]); +s.forEach(function(value, key, set) { + array.push(value); + if (key == 3) { + set.clear(); + set.add("four"); + } +}); +assertEqualArrays(array, [1, 2, 3, "four"]); + +array = []; +s = new Set([1, 2, 3]); +s.forEach(function(value, key, set) { + array.push(value); + if (key == 1) { + set.delete(1); + } + if (key == 2) { + set.delete(3); + } +}); +assertEqualArrays(array, [1, 2]); + +array = []; +s = new Set([1, 2, 3]); +s.forEach(function(value, key, set) { + array.push(value); + if (key < 4) { + set.delete(key); + set.add(key + 3) + } +}); +assertEqualArrays(array, [1, 2, 3, 4, 5, 6]); + + diff --git a/nashorn/test/script/basic/es6/weakmap.js b/nashorn/test/script/basic/es6/weakmap.js new file mode 100644 index 00000000000..2f53bd06373 --- /dev/null +++ b/nashorn/test/script/basic/es6/weakmap.js @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * JDK-8147558: Add support for ES6 collections + * + * @test + * @run + * @option --language=es6 + */ + +function assertThrows(src, error) { + try { + eval(src); + Assert.fail("No error, expected " + error); + } catch (e) { + if (!(e instanceof error)) { + Assert.fail("Wrong error, expected " + error + " but got " + e); + } + } +} + +// WeakMap constructor and prototype + +var desc = Object.getOwnPropertyDescriptor(this, "WeakMap"); +Assert.assertEquals(desc.writable, true); +Assert.assertEquals(desc.configurable, true); +Assert.assertEquals(desc.enumerable, false); + +Assert.assertTrue(Object.getPrototypeOf(new WeakMap()) === WeakMap.prototype); +Assert.assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype); +Assert.assertTrue(Object.getPrototypeOf(new WeakMap("")) === WeakMap.prototype); +Assert.assertTrue(Object.getPrototypeOf(new WeakMap([])) === WeakMap.prototype); + +assertThrows("WeakMap()", TypeError); +assertThrows("new WeakMap(3)", TypeError); +assertThrows("new WeakMap({})", TypeError); +assertThrows("new WeakMap([['a', {}]])", TypeError); +assertThrows("new WeakMap([[3, {}]])", TypeError); +assertThrows("new WeakMap([[true, {}]])", TypeError); +assertThrows("new WeakMap([[Symbol.iterator, {}]])", TypeError); + +assertThrows("WeakMap.prototype.set.apply({}, [{}, {}])", TypeError); +assertThrows("WeakMap.prototype.has.apply(3, [{}])", TypeError); +assertThrows("WeakMap.prototype.delete.apply('', [3])", TypeError); + +// WeakMap methods + +let values = [[{}, 1], [{}, 2], [{}, 3]]; +let m = new WeakMap(values); + +for (let i = 0; i < values.length; i++) { + Assert.assertTrue(m.has(values[i][0]) === true); + Assert.assertTrue(m.get(values[i][0]) === values[i][1]); + Assert.assertTrue(m.delete(values[i][0]) === true); + Assert.assertTrue(m.has(values[i][0]) === false); +} + +values.forEach(function(v) { + Assert.assertTrue(m.set(v[0], v[1]) === m); +}); + +for (let i = 0; i < values.length; i++) { + Assert.assertTrue(m.has(values[i][0]) === true); + Assert.assertTrue(m.get(values[i][0]) === values[i][1]); + Assert.assertTrue(m.delete(values[i][0]) === true); + Assert.assertTrue(m.has(values[i][0]) === false); +} + +// Primitive keys + +assertThrows("m.set('a', {})", TypeError); +assertThrows("m.set(3, {})", TypeError); +assertThrows("m.set(false, {})", TypeError); +assertThrows("m.set(Symbol.iterator, {})", TypeError); + +Assert.assertTrue(m.has('a') === false); +Assert.assertTrue(m.delete(3) === false); +Assert.assertTrue(m.get(Symbol.iterator) === undefined); +Assert.assertTrue(m.get(true) === undefined); diff --git a/nashorn/test/script/basic/es6/weakset.js b/nashorn/test/script/basic/es6/weakset.js new file mode 100644 index 00000000000..48cd0251bdd --- /dev/null +++ b/nashorn/test/script/basic/es6/weakset.js @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * JDK-8147558: Add support for ES6 collections + * + * @test + * @run + * @option --language=es6 + */ + +function assertThrows(src, error) { + try { + eval(src); + Assert.fail("No error, expected " + error); + } catch (e) { + if (!(e instanceof error)) { + Assert.fail("Wrong error, expected " + error + " but got " + e); + } + } +} + +// WeakSet constructor and prototype + +var desc = Object.getOwnPropertyDescriptor(this, "WeakSet"); +Assert.assertEquals(desc.writable, true); +Assert.assertEquals(desc.configurable, true); +Assert.assertEquals(desc.enumerable, false); + +Assert.assertTrue(Object.getPrototypeOf(new WeakSet()) === WeakSet.prototype); +Assert.assertTrue(Object.getPrototypeOf(WeakSet.prototype) === Object.prototype); +Assert.assertTrue(Object.getPrototypeOf(new WeakSet("")) === WeakSet.prototype); +Assert.assertTrue(Object.getPrototypeOf(new WeakSet([])) === WeakSet.prototype); + +assertThrows("WeakSet()", TypeError); +assertThrows("new WeakSet(3)", TypeError); +assertThrows("new WeakSet({})", TypeError); +assertThrows("new WeakSet(['a'])", TypeError); +assertThrows("new WeakSet([3])", TypeError); +assertThrows("new WeakSet([true])", TypeError); +assertThrows("new WeakSet([Symbol.iterator])", TypeError); + +assertThrows("WeakSet.prototype.add.apply({}, [''])", TypeError); +assertThrows("WeakSet.prototype.has.apply(3, [''])", TypeError); +assertThrows("WeakSet.prototype.delete.apply('', [3])", TypeError); + +// WeakSet methods + +let values = [{}, {}, {}]; +let s = new WeakSet(values); + +for (let i = 0; i < values.length; i++) { + Assert.assertTrue(s.has(values[i]) === true); + Assert.assertTrue(s.delete(values[i]) === true); + Assert.assertTrue(s.has(values[i]) === false); +} + +values.forEach(function(v) { + Assert.assertTrue(s.add(v) === s); +}); + +for (let i = 0; i < values.length; i++) { + Assert.assertTrue(s.has(values[i]) === true); + Assert.assertTrue(s.delete(values[i]) === true); + Assert.assertTrue(s.has(values[i]) === false); +} + +// Primitive keys + +assertThrows("s.add('a')", TypeError); +assertThrows("s.add(3)", TypeError); +assertThrows("s.add(false)", TypeError); +assertThrows("s.add(Symbol.iterator)", TypeError); + +Assert.assertTrue(s.has('a') === false); +Assert.assertTrue(s.delete(3) === false); +Assert.assertTrue(s.has(Symbol.iterator) === false); +Assert.assertTrue(s.delete(true) === false); + + From 88a8d4719e68e0a34eb2e90bef5d82cc1cb0b4c9 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 15 Feb 2016 14:02:57 -0800 Subject: [PATCH 095/139] 8149773: StandardDocFileFactory should be converted to use java.nio.file.Path Reviewed-by: ksrini --- .../internal/toolkit/Configuration.java | 16 - .../toolkit/resources/doclets.properties | 1 - .../toolkit/util/SimpleDocFileFactory.java | 292 ------------------ .../toolkit/util/StandardDocFileFactory.java | 82 ++--- .../doclets/toolkit/Configuration.java | 37 --- .../toolkit/resources/doclets.properties | 1 - .../toolkit/util/SimpleDocFileFactory.java | 291 ----------------- .../toolkit/util/StandardDocFileFactory.java | 83 ++--- 8 files changed, 90 insertions(+), 713 deletions(-) delete mode 100644 langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java delete mode 100644 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/SimpleDocFileFactory.java diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java index 07936a8d1c9..85dcb071b7e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java @@ -212,13 +212,6 @@ public abstract class Configuration { * used.Default is don't show version information. */ public boolean showversion = false; - - /** - * Sourcepath from where to read the source files. Default is classpath. - * - */ - public String sourcepath = ""; - /** * Argument for command line option "-Xprofilespath". */ @@ -492,11 +485,6 @@ public abstract class Configuration { showversion = true; } else if (opt.equals("-nodeprecated")) { nodeprecated = true; - } else if (opt.equals("-sourcepath")) { - sourcepath = os[1]; - } else if ((opt.equals("-classpath") || opt.equals("-cp")) && - sourcepath.length() == 0) { - sourcepath = os[1]; } else if (opt.equals("-excludedocfilessubdir")) { addToSet(excludedDocFileDirs, os[1]); } else if (opt.equals("-noqualifier")) { @@ -541,10 +529,6 @@ public abstract class Configuration { extern.link(url, pkglisturl, root, true); } } - if (sourcepath.length() == 0) { - sourcepath = System.getProperty("env.class.path") == null ? "" : - System.getProperty("env.class.path"); - } if (docencoding == null) { docencoding = encoding; } diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties index 5d4e330a265..f6e10be7195 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties @@ -23,7 +23,6 @@ doclet.Copy_Overwrite_warning=File {0} not copied to {1} due to existing file wi doclet.Copying_File_0_To_Dir_1=Copying file {0} to directory {1}... doclet.Copying_File_0_To_File_1=Copying file {0} to file {1}... doclet.No_Public_Classes_To_Document=No public or protected classes found to document. -doclet.Unable_to_create_directory_0=Unable to create directory {0} doclet.destination_directory_not_directory_0=Destination directory is not a directory {0} doclet.destination_directory_not_writable_0=Destination directory not writable {0} doclet.Encoding_not_supported=Encoding not supported: {0} diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java deleted file mode 100644 index ad7d024c049..00000000000 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.doclets.internal.toolkit.util; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import javax.tools.DocumentationTool; -import javax.tools.JavaFileManager.Location; -import javax.tools.StandardLocation; - -import com.sun.tools.doclets.internal.toolkit.Configuration; - -/** - * Implementation of DocFileFactory that just uses java.io.File API, - * and does not use a JavaFileManager.. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - * - * @since 1.8 - */ -class SimpleDocFileFactory extends DocFileFactory { - - public SimpleDocFileFactory(Configuration configuration) { - super(configuration); - } - - public DocFile createFileForDirectory(String file) { - return new SimpleDocFile(new File(file)); - } - - public DocFile createFileForInput(String file) { - return new SimpleDocFile(new File(file)); - } - - public DocFile createFileForOutput(DocPath path) { - return new SimpleDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path); - } - - @Override - Iterable list(Location location, DocPath path) { - if (location != StandardLocation.SOURCE_PATH) - throw new IllegalArgumentException(); - - Set files = new LinkedHashSet<>(); - for (String s : configuration.sourcepath.split(File.pathSeparator)) { - if (s.isEmpty()) - continue; - File f = new File(s); - if (f.isDirectory()) { - f = new File(f, path.getPath()); - if (f.exists()) - files.add(new SimpleDocFile(f)); - } - } - return files; - } - - class SimpleDocFile extends DocFile { - private File file; - - /** Create a DocFile for a given file. */ - private SimpleDocFile(File file) { - super(configuration); - this.file = file; - } - - /** Create a DocFile for a given location and relative path. */ - private SimpleDocFile(Location location, DocPath path) { - super(configuration, location, path); - String destDirName = configuration.destDirName; - this.file = destDirName.isEmpty() ? new File(path.getPath()) - : new File(destDirName, path.getPath()); - } - - /** Open an input stream for the file. */ - public InputStream openInputStream() throws FileNotFoundException { - return new BufferedInputStream(new FileInputStream(file)); - } - - /** - * Open an output stream for the file. - * The file must have been created with a location of - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path. - */ - public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException { - if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT) - throw new IllegalStateException(); - - createDirectoryForFile(file); - return new BufferedOutputStream(new FileOutputStream(file)); - } - - /** - * Open an writer for the file, using the encoding (if any) given in the - * doclet configuration. - * The file must have been created with a location of - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path. - */ - public Writer openWriter() throws IOException, UnsupportedEncodingException { - if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT) - throw new IllegalStateException(); - - createDirectoryForFile(file); - FileOutputStream fos = new FileOutputStream(file); - if (configuration.docencoding == null) { - return new BufferedWriter(new OutputStreamWriter(fos)); - } else { - return new BufferedWriter(new OutputStreamWriter(fos, configuration.docencoding)); - } - } - - /** Return true if the file can be read. */ - public boolean canRead() { - return file.canRead(); - } - - /** Return true if the file can be written. */ - public boolean canWrite() { - return file.canRead(); - } - - /** Return true if the file exists. */ - public boolean exists() { - return file.exists(); - } - - /** Return the base name (last component) of the file name. */ - public String getName() { - return file.getName(); - } - - /** Return the file system path for this file. */ - public String getPath() { - return file.getPath(); - } - - /** Return true is file has an absolute path name. */ - public boolean isAbsolute() { - return file.isAbsolute(); - } - - /** Return true is file identifies a directory. */ - public boolean isDirectory() { - return file.isDirectory(); - } - - /** Return true is file identifies a file. */ - public boolean isFile() { - return file.isFile(); - } - - /** Return true if this file is the same as another. */ - public boolean isSameFile(DocFile other) { - if (!(other instanceof SimpleDocFile)) - return false; - - try { - return file.exists() - && file.getCanonicalFile().equals(((SimpleDocFile)other).file.getCanonicalFile()); - } catch (IOException e) { - return false; - } - } - - /** If the file is a directory, list its contents. */ - public Iterable list() { - List files = new ArrayList<>(); - for (File f: file.listFiles()) { - files.add(new SimpleDocFile(f)); - } - return files; - } - - /** Create the file as a directory, including any parent directories. */ - public boolean mkdirs() { - return file.mkdirs(); - } - - /** - * Derive a new file by resolving a relative path against this file. - * The new file will inherit the configuration and location of this file - * If this file has a path set, the new file will have a corresponding - * new path. - */ - public DocFile resolve(DocPath p) { - return resolve(p.getPath()); - } - - /** - * Derive a new file by resolving a relative path against this file. - * The new file will inherit the configuration and location of this file - * If this file has a path set, the new file will have a corresponding - * new path. - */ - public DocFile resolve(String p) { - if (location == null && path == null) { - return new SimpleDocFile(new File(file, p)); - } else { - return new SimpleDocFile(location, path.resolve(p)); - } - } - - /** - * Resolve a relative file against the given output location. - * @param locn Currently, only - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported. - */ - public DocFile resolveAgainst(Location locn) { - if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT) - throw new IllegalArgumentException(); - return new SimpleDocFile( - new File(configuration.destDirName, file.getPath())); - } - - /** - * Given a path string create all the directories in the path. For example, - * if the path string is "java/applet", the method will create directory - * "java" and then "java/applet" if they don't exist. The file separator - * string "/" is platform dependent system property. - * - * @param path Directory path string. - */ - private void createDirectoryForFile(File file) { - File dir = file.getParentFile(); - if (dir == null || dir.exists() || dir.mkdirs()) - return; - - configuration.message.error( - "doclet.Unable_to_create_directory_0", dir.getPath()); - throw new DocletAbortException("can't create directory"); - } - - /** Return a string to identify the contents of this object, - * for debugging purposes. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("DocFile["); - if (location != null) - sb.append("locn:").append(location).append(","); - if (path != null) - sb.append("path:").append(path.getPath()).append(","); - sb.append("file:").append(file); - sb.append("]"); - return sb.toString(); - } - - } -} diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java index 74c81a255e6..2c2941dc731 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * 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,13 +28,16 @@ package com.sun.tools.doclets.internal.toolkit.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; @@ -63,37 +66,37 @@ import com.sun.tools.javac.util.Assert; */ class StandardDocFileFactory extends DocFileFactory { private final StandardJavaFileManager fileManager; - private File destDir; + private Path destDir; public StandardDocFileFactory(Configuration configuration) { super(configuration); fileManager = (StandardJavaFileManager) configuration.getFileManager(); } - private File getDestDir() { + private Path getDestDir() { if (destDir == null) { if (!configuration.destDirName.isEmpty() || !fileManager.hasLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT)) { try { String dirName = configuration.destDirName.isEmpty() ? "." : configuration.destDirName; - File dir = new File(dirName); - fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir)); + Path dir = Paths.get(dirName); + fileManager.setLocationFromPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir)); } catch (IOException e) { throw new DocletAbortException(e); } } - destDir = fileManager.getLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next(); + destDir = fileManager.getLocationAsPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next(); } return destDir; } public DocFile createFileForDirectory(String file) { - return new StandardDocFile(new File(file)); + return new StandardDocFile(Paths.get(file)); } public DocFile createFileForInput(String file) { - return new StandardDocFile(new File(file)); + return new StandardDocFile(Paths.get(file)); } public DocFile createFileForOutput(DocPath path) { @@ -108,26 +111,25 @@ class StandardDocFileFactory extends DocFileFactory { Set files = new LinkedHashSet<>(); Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; - for (File f: fileManager.getLocation(l)) { - if (f.isDirectory()) { - f = new File(f, path.getPath()); - if (f.exists()) + for (Path f: fileManager.getLocationAsPaths(l)) { + if (Files.isDirectory(f)) { + f = f.resolve(path.getPath()); + if (Files.exists(f)) files.add(new StandardDocFile(f)); } } return files; } - private static File newFile(File dir, String path) { - return (dir == null) ? new File(path) : new File(dir, path); + private static Path newFile(Path dir, String path) { + return (dir == null) ? Paths.get(path) : dir.resolve(path); } class StandardDocFile extends DocFile { - private File file; - + private Path file; /** Create a StandardDocFile for a given file. */ - private StandardDocFile(File file) { + private StandardDocFile(Path file) { super(configuration); this.file = file; } @@ -178,27 +180,27 @@ class StandardDocFileFactory extends DocFileFactory { /** Return true if the file can be read. */ public boolean canRead() { - return file.canRead(); + return Files.isReadable(file); } /** Return true if the file can be written. */ public boolean canWrite() { - return file.canWrite(); + return Files.isWritable(file); } /** Return true if the file exists. */ public boolean exists() { - return file.exists(); + return Files.exists(file); } /** Return the base name (last component) of the file name. */ public String getName() { - return file.getName(); + return file.getFileName().toString(); } /** Return the file system path for this file. */ public String getPath() { - return file.getPath(); + return file.toString(); } /** Return true is file has an absolute path name. */ @@ -208,12 +210,12 @@ class StandardDocFileFactory extends DocFileFactory { /** Return true is file identifies a directory. */ public boolean isDirectory() { - return file.isDirectory(); + return Files.isDirectory(file); } /** Return true is file identifies a file. */ public boolean isFile() { - return file.isFile(); + return Files.isRegularFile(file); } /** Return true if this file is the same as another. */ @@ -222,25 +224,31 @@ class StandardDocFileFactory extends DocFileFactory { return false; try { - return file.exists() - && file.getCanonicalFile().equals(((StandardDocFile) other).file.getCanonicalFile()); + return Files.isSameFile(file, ((StandardDocFile) other).file); } catch (IOException e) { return false; } } /** If the file is a directory, list its contents. */ - public Iterable list() { - List files = new ArrayList<>(); - for (File f: file.listFiles()) { - files.add(new StandardDocFile(f)); + public Iterable list() throws IOException { + List files = new ArrayList(); + try (DirectoryStream ds = Files.newDirectoryStream(file)) { + for (Path f: ds) { + files.add(new StandardDocFile(f)); + } } return files; } /** Create the file as a directory, including any parent directories. */ public boolean mkdirs() { - return file.mkdirs(); + try { + Files.createDirectories(file); + return true; + } catch (IOException e) { + return false; + } } /** @@ -261,7 +269,7 @@ class StandardDocFileFactory extends DocFileFactory { */ public DocFile resolve(String p) { if (location == null && path == null) { - return new StandardDocFile(new File(file, p)); + return new StandardDocFile(file.resolve(p)); } else { return new StandardDocFile(location, path.resolve(p)); } @@ -270,12 +278,12 @@ class StandardDocFileFactory extends DocFileFactory { /** * Resolve a relative file against the given output location. * @param locn Currently, only - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported. + * {@link DocumentationTool.Location.DOCUMENTATION_OUTPUT} is supported. */ public DocFile resolveAgainst(Location locn) { if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT) throw new IllegalArgumentException(); - return new StandardDocFile(newFile(getDestDir(), file.getPath())); + return new StandardDocFile(getDestDir().resolve(file)); } /** Return a string to identify the contents of this object, @@ -284,7 +292,7 @@ class StandardDocFileFactory extends DocFileFactory { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("StandardDocFile["); + sb.append("PathDocFile["); if (location != null) sb.append("locn:").append(location).append(","); if (path != null) @@ -294,7 +302,7 @@ class StandardDocFileFactory extends DocFileFactory { return sb.toString(); } - private JavaFileObject getJavaFileObjectForInput(File file) { + private JavaFileObject getJavaFileObjectForInput(Path file) { return fileManager.getJavaFileObjects(file).iterator().next(); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java index 24d5585ab3f..9577631405d 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java @@ -239,12 +239,6 @@ public abstract class Configuration { */ public boolean showversion = false; - /** - * Sourcepath from where to read the source files. Default is classpath. - * - */ - public String sourcepath = ""; - /** * Don't generate deprecated API information at all, if -nodeprecated * option is used. nodepracted is set to true if @@ -389,26 +383,6 @@ public abstract class Configuration { return true; } }, - new Hidden(this, "classpath", 1) { - @Override - public boolean process(String opt, ListIterator args) { - if (sourcepath.length() == 0) { - optionsProcessed.add(this); - sourcepath = args.next(); - } - return true; - } - }, - new Hidden(this, "cp", 1) { - @Override - public boolean process(String opt, ListIterator args) { - if (sourcepath.length() == 0) { - optionsProcessed.add(this); - sourcepath = args.next(); - } - return true; - } - }, new Option(this, "d", 1) { @Override public boolean process(String opt, ListIterator args) { @@ -555,14 +529,6 @@ public abstract class Configuration { return true; } }, - new Hidden(this, "sourcepath", 1) { - @Override - public boolean process(String opt, ListIterator args) { - optionsProcessed.add(this); - sourcepath = args.next(); - return true; - } - }, new Option(this, "sourcetab", 1) { @Override public boolean process(String opt, ListIterator args) { @@ -638,9 +604,6 @@ public abstract class Configuration { extern.link(urlForLink, pkglistUrlForLink, reporter, false); if (urlForLinkOffline != null && pkglistUrlForLinkOffline != null) extern.link(urlForLinkOffline, pkglistUrlForLinkOffline, reporter, true); - if (sourcepath.length() == 0) { - sourcepath = System.getProperty("env.class.path", ""); - } if (docencoding == null) { docencoding = encoding; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index 515fcf59778..a4b574dba15 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -23,7 +23,6 @@ doclet.Copy_Overwrite_warning=File {0} not copied to {1} due to existing file wi doclet.Copying_File_0_To_Dir_1=Copying file {0} to directory {1}... doclet.Copying_File_0_To_File_1=Copying file {0} to file {1}... doclet.No_Public_Classes_To_Document=No public or protected classes found to document. -doclet.Unable_to_create_directory_0=Unable to create directory {0} doclet.destination_directory_not_directory_0=Destination directory is not a directory {0} doclet.destination_directory_not_writable_0=Destination directory not writable {0} doclet.Encoding_not_supported=Encoding not supported: {0} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/SimpleDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/SimpleDocFileFactory.java deleted file mode 100644 index ca1a5f1adc4..00000000000 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/SimpleDocFileFactory.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.javadoc.internal.doclets.toolkit.util; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import javax.tools.DocumentationTool; -import javax.tools.JavaFileManager.Location; -import javax.tools.StandardLocation; - -import jdk.javadoc.internal.doclets.toolkit.Configuration; - -/** - * Implementation of DocFileFactory that just uses java.io.File API, - * and does not use a JavaFileManager.. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - * - */ -class SimpleDocFileFactory extends DocFileFactory { - - public SimpleDocFileFactory(Configuration configuration) { - super(configuration); - } - - public DocFile createFileForDirectory(String file) { - return new SimpleDocFile(new File(file)); - } - - public DocFile createFileForInput(String file) { - return new SimpleDocFile(new File(file)); - } - - public DocFile createFileForOutput(DocPath path) { - return new SimpleDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path); - } - - @Override - Iterable list(Location location, DocPath path) { - if (location != StandardLocation.SOURCE_PATH) - throw new IllegalArgumentException(); - - Set files = new LinkedHashSet<>(); - for (String s : configuration.sourcepath.split(File.pathSeparator)) { - if (s.isEmpty()) - continue; - File f = new File(s); - if (f.isDirectory()) { - f = new File(f, path.getPath()); - if (f.exists()) - files.add(new SimpleDocFile(f)); - } - } - return files; - } - - class SimpleDocFile extends DocFile { - private File file; - - /** Create a DocFile for a given file. */ - private SimpleDocFile(File file) { - super(configuration); - this.file = file; - } - - /** Create a DocFile for a given location and relative path. */ - private SimpleDocFile(Location location, DocPath path) { - super(configuration, location, path); - String destDirName = configuration.destDirName; - this.file = destDirName.isEmpty() ? new File(path.getPath()) - : new File(destDirName, path.getPath()); - } - - /** Open an input stream for the file. */ - public InputStream openInputStream() throws FileNotFoundException { - return new BufferedInputStream(new FileInputStream(file)); - } - - /** - * Open an output stream for the file. - * The file must have been created with a location of - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path. - */ - public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException { - if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT) - throw new IllegalStateException(); - - createDirectoryForFile(file); - return new BufferedOutputStream(new FileOutputStream(file)); - } - - /** - * Open an writer for the file, using the encoding (if any) given in the - * doclet configuration. - * The file must have been created with a location of - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path. - */ - public Writer openWriter() throws IOException, UnsupportedEncodingException { - if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT) - throw new IllegalStateException(); - - createDirectoryForFile(file); - FileOutputStream fos = new FileOutputStream(file); - if (configuration.docencoding == null) { - return new BufferedWriter(new OutputStreamWriter(fos)); - } else { - return new BufferedWriter(new OutputStreamWriter(fos, configuration.docencoding)); - } - } - - /** Return true if the file can be read. */ - public boolean canRead() { - return file.canRead(); - } - - /** Return true if the file can be written. */ - public boolean canWrite() { - return file.canRead(); - } - - /** Return true if the file exists. */ - public boolean exists() { - return file.exists(); - } - - /** Return the base name (last component) of the file name. */ - public String getName() { - return file.getName(); - } - - /** Return the file system path for this file. */ - public String getPath() { - return file.getPath(); - } - - /** Return true is file has an absolute path name. */ - public boolean isAbsolute() { - return file.isAbsolute(); - } - - /** Return true is file identifies a directory. */ - public boolean isDirectory() { - return file.isDirectory(); - } - - /** Return true is file identifies a file. */ - public boolean isFile() { - return file.isFile(); - } - - /** Return true if this file is the same as another. */ - public boolean isSameFile(DocFile other) { - if (!(other instanceof SimpleDocFile)) - return false; - - try { - return file.exists() - && file.getCanonicalFile().equals(((SimpleDocFile)other).file.getCanonicalFile()); - } catch (IOException e) { - return false; - } - } - - /** If the file is a directory, list its contents. */ - public Iterable list() { - List files = new ArrayList<>(); - for (File f: file.listFiles()) { - files.add(new SimpleDocFile(f)); - } - return files; - } - - /** Create the file as a directory, including any parent directories. */ - public boolean mkdirs() { - return file.mkdirs(); - } - - /** - * Derive a new file by resolving a relative path against this file. - * The new file will inherit the configuration and location of this file - * If this file has a path set, the new file will have a corresponding - * new path. - */ - public DocFile resolve(DocPath p) { - return resolve(p.getPath()); - } - - /** - * Derive a new file by resolving a relative path against this file. - * The new file will inherit the configuration and location of this file - * If this file has a path set, the new file will have a corresponding - * new path. - */ - public DocFile resolve(String p) { - if (location == null && path == null) { - return new SimpleDocFile(new File(file, p)); - } else { - return new SimpleDocFile(location, path.resolve(p)); - } - } - - /** - * Resolve a relative file against the given output location. - * @param locn Currently, only - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported. - */ - public DocFile resolveAgainst(Location locn) { - if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT) - throw new IllegalArgumentException(); - return new SimpleDocFile( - new File(configuration.destDirName, file.getPath())); - } - - /** - * Given a path string create all the directories in the path. For example, - * if the path string is "java/applet", the method will create directory - * "java" and then "java/applet" if they don't exist. The file separator - * string "/" is platform dependent system property. - * - * @param path Directory path string. - */ - private void createDirectoryForFile(File file) { - File dir = file.getParentFile(); - if (dir == null || dir.exists() || dir.mkdirs()) - return; - - configuration.message.error( - "doclet.Unable_to_create_directory_0", dir.getPath()); - throw new DocletAbortException("can't create directory"); - } - - /** Return a string to identify the contents of this object, - * for debugging purposes. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("DocFile["); - if (location != null) - sb.append("locn:").append(location).append(","); - if (path != null) - sb.append("path:").append(path.getPath()).append(","); - sb.append("file:").append(file); - sb.append("]"); - return sb.toString(); - } - - } -} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java index cb5fe3e06c4..004fcb14a0b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java @@ -28,13 +28,16 @@ package jdk.javadoc.internal.doclets.toolkit.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; @@ -48,6 +51,7 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; +import com.sun.tools.javac.util.Assert; import jdk.javadoc.internal.doclets.toolkit.Configuration; /** @@ -61,37 +65,37 @@ import jdk.javadoc.internal.doclets.toolkit.Configuration; */ class StandardDocFileFactory extends DocFileFactory { private final StandardJavaFileManager fileManager; - private File destDir; + private Path destDir; public StandardDocFileFactory(Configuration configuration) { super(configuration); fileManager = (StandardJavaFileManager) configuration.getFileManager(); } - private File getDestDir() { + private Path getDestDir() { if (destDir == null) { if (!configuration.destDirName.isEmpty() || !fileManager.hasLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT)) { try { String dirName = configuration.destDirName.isEmpty() ? "." : configuration.destDirName; - File dir = new File(dirName); - fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir)); + Path dir = Paths.get(dirName); + fileManager.setLocationFromPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir)); } catch (IOException e) { throw new DocletAbortException(e); } } - destDir = fileManager.getLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next(); + destDir = fileManager.getLocationAsPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next(); } return destDir; } public DocFile createFileForDirectory(String file) { - return new StandardDocFile(new File(file)); + return new StandardDocFile(Paths.get(file)); } public DocFile createFileForInput(String file) { - return new StandardDocFile(new File(file)); + return new StandardDocFile(Paths.get(file)); } public DocFile createFileForOutput(DocPath path) { @@ -106,26 +110,25 @@ class StandardDocFileFactory extends DocFileFactory { Set files = new LinkedHashSet<>(); Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; - for (File f: fileManager.getLocation(l)) { - if (f.isDirectory()) { - f = new File(f, path.getPath()); - if (f.exists()) + for (Path f: fileManager.getLocationAsPaths(l)) { + if (Files.isDirectory(f)) { + f = f.resolve(path.getPath()); + if (Files.exists(f)) files.add(new StandardDocFile(f)); } } return files; } - private static File newFile(File dir, String path) { - return (dir == null) ? new File(path) : new File(dir, path); + private static Path newFile(Path dir, String path) { + return (dir == null) ? Paths.get(path) : dir.resolve(path); } class StandardDocFile extends DocFile { - private File file; - + private Path file; /** Create a StandardDocFile for a given file. */ - private StandardDocFile(File file) { + private StandardDocFile(Path file) { super(configuration); this.file = file; } @@ -133,9 +136,7 @@ class StandardDocFileFactory extends DocFileFactory { /** Create a StandardDocFile for a given location and relative path. */ private StandardDocFile(Location location, DocPath path) { super(configuration, location, path); - if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT) { - throw new AssertionError("invalid location output"); - } + Assert.check(location == DocumentationTool.Location.DOCUMENTATION_OUTPUT); this.file = newFile(getDestDir(), path.getPath()); } @@ -178,27 +179,27 @@ class StandardDocFileFactory extends DocFileFactory { /** Return true if the file can be read. */ public boolean canRead() { - return file.canRead(); + return Files.isReadable(file); } /** Return true if the file can be written. */ public boolean canWrite() { - return file.canWrite(); + return Files.isWritable(file); } /** Return true if the file exists. */ public boolean exists() { - return file.exists(); + return Files.exists(file); } /** Return the base name (last component) of the file name. */ public String getName() { - return file.getName(); + return file.getFileName().toString(); } /** Return the file system path for this file. */ public String getPath() { - return file.getPath(); + return file.toString(); } /** Return true is file has an absolute path name. */ @@ -208,12 +209,12 @@ class StandardDocFileFactory extends DocFileFactory { /** Return true is file identifies a directory. */ public boolean isDirectory() { - return file.isDirectory(); + return Files.isDirectory(file); } /** Return true is file identifies a file. */ public boolean isFile() { - return file.isFile(); + return Files.isRegularFile(file); } /** Return true if this file is the same as another. */ @@ -222,25 +223,31 @@ class StandardDocFileFactory extends DocFileFactory { return false; try { - return file.exists() - && file.getCanonicalFile().equals(((StandardDocFile) other).file.getCanonicalFile()); + return Files.isSameFile(file, ((StandardDocFile) other).file); } catch (IOException e) { return false; } } /** If the file is a directory, list its contents. */ - public Iterable list() { - List files = new ArrayList<>(); - for (File f: file.listFiles()) { - files.add(new StandardDocFile(f)); + public Iterable list() throws IOException { + List files = new ArrayList(); + try (DirectoryStream ds = Files.newDirectoryStream(file)) { + for (Path f: ds) { + files.add(new StandardDocFile(f)); + } } return files; } /** Create the file as a directory, including any parent directories. */ public boolean mkdirs() { - return file.mkdirs(); + try { + Files.createDirectories(file); + return true; + } catch (IOException e) { + return false; + } } /** @@ -261,7 +268,7 @@ class StandardDocFileFactory extends DocFileFactory { */ public DocFile resolve(String p) { if (location == null && path == null) { - return new StandardDocFile(new File(file, p)); + return new StandardDocFile(file.resolve(p)); } else { return new StandardDocFile(location, path.resolve(p)); } @@ -270,12 +277,12 @@ class StandardDocFileFactory extends DocFileFactory { /** * Resolve a relative file against the given output location. * @param locn Currently, only - * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported. + * {@link DocumentationTool.Location.DOCUMENTATION_OUTPUT} is supported. */ public DocFile resolveAgainst(Location locn) { if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT) throw new IllegalArgumentException(); - return new StandardDocFile(newFile(getDestDir(), file.getPath())); + return new StandardDocFile(getDestDir().resolve(file)); } /** Return a string to identify the contents of this object, @@ -294,7 +301,7 @@ class StandardDocFileFactory extends DocFileFactory { return sb.toString(); } - private JavaFileObject getJavaFileObjectForInput(File file) { + private JavaFileObject getJavaFileObjectForInput(Path file) { return fileManager.getJavaFileObjects(file).iterator().next(); } From 589abd0822a17c5ba206eff93bd4e49bc4c83e92 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 22 Feb 2016 11:23:03 +0100 Subject: [PATCH 096/139] 8150203: Incremental update from build-infra project Reviewed-by: erikj --- jdk/make/gensrc/GensrcMisc.gmk | 16 +++++++++------- jdk/make/lib/Awt2dLibraries.gmk | 6 +++--- jdk/make/lib/CoreLibraries.gmk | 6 +++--- jdk/make/lib/Lib-java.instrument.gmk | 3 +-- jdk/make/lib/Lib-jdk.jdi.gmk | 3 +-- jdk/make/lib/Lib-jdk.jdwp.agent.gmk | 3 +-- .../build/tools/dtdbuilder/DTDParser.java | 6 +----- 7 files changed, 19 insertions(+), 24 deletions(-) diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk index bc70e0e01f0..ffefb50a5b0 100644 --- a/jdk/make/gensrc/GensrcMisc.gmk +++ b/jdk/make/gensrc/GensrcMisc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,8 @@ SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSRC_SOR_SRC)/$(GENSRC_SOR_SRC_FILE) | $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \ SRC := $(GENSRC_SOR_SRC), \ INCLUDE_FILES := $(GENSRC_SOR_SRC_FILE), \ + CFLAGS_windows := -nologo, \ + LDFLAGS_windows := -nologo, \ TOOLCHAIN := TOOLCHAIN_BUILD, \ OBJECT_DIR := $(GENSRC_SOR_BIN), \ OUTPUT_DIR := $(GENSRC_SOR_BIN), \ @@ -61,12 +63,12 @@ $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \ SOR_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/ch/SocketOptionRegistry-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template ifeq ($(wildcard $(SOR_PREGEN_FILE)), ) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOR_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_SOR_EXE) >> $@.tmp + $(BUILD_GENSRC_SOR_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ else $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(SOR_PREGEN_FILE) @@ -97,12 +99,12 @@ ifneq ($(OPENJDK_TARGET_OS), windows) UC_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/fs/UnixConstants-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template ifeq ($(wildcard $(UC_PREGEN_FILE)), ) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(UC_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_UC_EXE) >> $@.tmp + $(BUILD_GENSRC_UC_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ else $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(UC_PREGEN_FILE) @@ -132,12 +134,12 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) OUTPUT_DIR := $(GENSRC_SOL_BIN), \ PROGRAM := genSolarisConstants)) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOL_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_SOL_EXE) >> $@.tmp + $(BUILD_GENSRC_SOL_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index ad58edb2823..d6ba6443bf2 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -593,8 +593,8 @@ ifeq ($(BUILD_HEADLESS), true) LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \ REORDER := $(LIBAWT_HEADLESS_REORDER), \ LIBS_unix := -lawt -ljvm -ljava, \ - LIBS_linux := -lm $(LIBDL), \ - LIBS_solaris := -lm $(LIBDL) $(LIBCXX) -lc, \ + LIBS_linux := $(LIBM) $(LIBDL), \ + LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \ )) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index ea7c7f3c991..bd707071427 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -163,7 +163,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBS_unix := -ljvm -lverify, \ LIBS_linux := $(LIBDL) $(BUILD_LIBFDLIBM), \ LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL) $(BUILD_LIBFDLIBM) -lc, \ - LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) -lm,\ + LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) $(LIBM),\ LIBS_macosx := -lfdlibm \ -framework CoreFoundation \ -framework Foundation \ @@ -225,7 +225,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \ -export:ZIP_ReadEntry -export:ZIP_GetNextEntry \ - -export:ZIP_InflateFully -export:ZIP_CRC32, \ + -export:ZIP_InflateFully, \ LIBS_unix := -ljvm -ljava $(LIBZ), \ LIBS_solaris := -lc, \ LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \ diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk index 02df76073af..44ba88dad40 100644 --- a/jdk/make/lib/Lib-java.instrument.gmk +++ b/jdk/make/lib/Lib-java.instrument.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \ -L$(call FindLibDirForModule, java.base)/jli, \ LDFLAGS_macosx := -Wl$(COMMA)-all_load, \ LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \ - LDFLAGS_windows := -export:Agent_OnAttach, \ LIBS := $(JDKLIB_LIBS), \ LIBS_unix := -ljava $(LIBZ), \ LIBS_linux := -ljli $(LIBDL), \ diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk index 8bed1f9abd1..bb1edfd1c23 100644 --- a/jdk/make/lib/Lib-jdk.jdi.gmk +++ b/jdk/make/lib/Lib-jdk.jdi.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows) CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SHMEM_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ - LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS := $(JDKLIB_LIBS), \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 198dc2c2433..84c05ba6368 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS_linux := -lpthread, \ LIBS_solaris := -lnsl -lsocket -lc, \ LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib, \ diff --git a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java index 0dee68e367f..8ef7cfe13b0 100644 --- a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java +++ b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -908,16 +908,12 @@ class DTDParser implements DTDConstants { this.dtd = dtd; this.in = new DTDInputStream(in, dtd); - long tm = System.currentTimeMillis(); ch = this.in.read(); parseSection(); if (ch != -1) { error("premature"); } - - tm = System.currentTimeMillis() - tm; - System.err.println("[Parsed DTD " + dtd + " in " + tm + "ms]"); } catch (IOException e) { error("ioexception"); } catch (Exception e) { From 0934254e0397496f7e271bea6fb803e96e529e11 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Tue, 23 Feb 2016 09:52:56 +0800 Subject: [PATCH 097/139] 8149154: tools/pack200/Pack200Test.java failed with NullPointerException Reviewed-by: ksrini --- jdk/test/tools/pack200/Pack200Test.java | 2 ++ jdk/test/tools/pack200/Utils.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index 9298e9723a8..fb6d9b1f83d 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -81,7 +81,9 @@ public class Pack200Test { System.out.println("Packing [" + in.toString() + "]"); // Call the packer Utils.pack(jarFile, packFile); + System.out.println("Done Packing [" + in.toString() + "]"); jarFile.close(); + System.out.println("Start leak check"); leakCheck(); System.out.println(" Unpacking using java unpacker"); diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java index f0c29a597b5..60f2d0c50bc 100644 --- a/jdk/test/tools/pack200/Utils.java +++ b/jdk/test/tools/pack200/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -324,6 +324,9 @@ class Utils { private static void findFiles0(File startDir, List list, FileFilter filter) throws IOException { File[] foundFiles = startDir.listFiles(filter); + if (foundFiles == null) { + return; + } list.addAll(Arrays.asList(foundFiles)); File[] dirs = startDir.listFiles(DIR_FILTER); for (File dir : dirs) { From 5baf4fccc46aa4ebc274f85accdb3da5757603cb Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Tue, 23 Feb 2016 07:17:54 +0100 Subject: [PATCH 098/139] 8150360: augment/correct MethodHandle API documentation Reviewed-by: psandoz --- .../java/lang/invoke/MethodHandle.java | 15 ++++++++-- .../java/lang/invoke/MethodHandles.java | 28 +++++++++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index a3f6f47b00f..235ffe60f57 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1026,6 +1026,9 @@ MethodHandle longsToString = publicLookup() .asCollector(long[].class, 1); assertEquals("[123]", (String) longsToString.invokeExact((long)123)); * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument * @return a new method handle which collects some trailing argument @@ -1067,6 +1070,9 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1); assertEquals("BCPQRSZ", swr.toString()); * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param collectArgPos the zero-based position in the parameter list at which to start collecting. * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument @@ -1356,8 +1362,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); * The reference {@code x} must be convertible to the first parameter * type of the target. *

- * (Note: Because method handles are immutable, the target method handle - * retains its original type and behavior.) + * Note: Because method handles are immutable, the target method handle + * retains its original type and behavior. + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param x the value to bind to the first argument of the target * @return a new method handle which prepends the given value to the incoming * argument list, before calling the original method handle diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index fc9ac8e1518..c7389b63b05 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2139,7 +2139,7 @@ return invoker; * if its index does not appear in the array. * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, * incoming arguments which are not mentioned in the reordering array - * are may be any type, as determined only by {@code newType}. + * may be of any type, as determined only by {@code newType}. *

{@code
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
@@ -2157,6 +2157,9 @@ MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
 assert(twice.type().equals(intfn1));
 assert((int)twice.invokeExact(21) == 42);
      * }
+ *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after arguments are reordered * @param newType the expected type of the new method handle * @param reorder an index array which controls the reordering @@ -2421,6 +2424,9 @@ assert((int)twice.invokeExact(21) == 42); * It may range between zero and N-L (inclusively), * where N is the arity of the target method handle * and L is the length of the values array. + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after the argument is inserted * @param pos where to insert the argument (zero for the first) * @param values the series of arguments to insert @@ -2647,6 +2653,9 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY * return target(p..., f[i](v[i])..., b...); * } * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after arguments are filtered * @param pos the position of the first argument to filter @@ -2791,6 +2800,9 @@ assertEquals("[top, [[up, down, strange], charm], bottom]", * a non-void result, then {@code collectArguments(mh, N, coll)} * is equivalent to {@code filterArguments(mh, N, coll)}. * Other equivalences are possible but would require argument permutation. + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after filtering the subsequence of arguments * @param pos the position of the first adapter argument to pass to the filter, @@ -2887,6 +2899,9 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 * filter3(v); * } * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke before filtering the return value * @param filter method handle to call on the return value * @return method handle which incorporates the specified return value filtering logic @@ -2981,6 +2996,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * return target2(a..., b...); * } * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after arguments are combined * @param combiner method handle to call initially on the incoming arguments * @return method handle which incorporates the specified argument folding logic @@ -3828,8 +3846,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * (Note that, except for argument type conversions, combinators represent {@code void} values in parameter lists * by omitting the corresponding paradoxical arguments, not by inserting {@code null} or zero values.) *

- * The {@code target} and {@code cleanup} handles' return types must be the same. Their parameter type lists also - * must be the same, but the {@code cleanup} handle must accept one or two more leading parameters:

    + * The {@code target} and {@code cleanup} handles must have the same corresponding argument and return types, except + * that the {@code cleanup} handle may omit trailing arguments. Also, the {@code cleanup} handle must have one or + * two extra leading parameters:
      *
    • a {@code Throwable}, which will carry the exception thrown by the {@code target} handle (if any); and *
    • a parameter of the same type as the return type of both {@code target} and {@code cleanup}, which will carry * the result from the execution of the {@code target} handle. @@ -3949,6 +3968,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * return target2(z..., a..., b...); * } * } + *

      + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after arguments are combined * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code From 28d990ee6fae99f1e35fca94fcb6d4a894efae64 Mon Sep 17 00:00:00 2001 From: Nishit Jain Date: Tue, 23 Feb 2016 17:09:46 +0900 Subject: [PATCH 099/139] 8074411: Describe "minor unit" and/or "default fraction digits" in Currency class' javadoc clearly Reviewed-by: naoto, okutsu, peytoia --- .../share/classes/java/util/Currency.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/Currency.java b/jdk/src/java.base/share/classes/java/util/Currency.java index 74c7b4bb3fc..8648147bcfe 100644 --- a/jdk/src/java.base/share/classes/java/util/Currency.java +++ b/jdk/src/java.base/share/classes/java/util/Currency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,7 +92,12 @@ import sun.util.logging.PlatformLogger; * and the remainder of entries in file are processed. For instances where duplicate * country code entries exist, the behavior of the Currency information for that * {@code Currency} is undefined and the remainder of entries in file are processed. + *

      + * It is recommended to use {@link java.math.BigDecimal} class while dealing + * with {@code Currency} or monetary values as it provides better handling of floating + * point numbers and their operations. * + * @see java.math.BigDecimal * @since 1.4 */ public final class Currency implements Serializable { @@ -516,14 +521,16 @@ public final class Currency implements Serializable { } /** - * Gets the default number of fraction digits used with this currency. - * For example, the default number of fraction digits for the Euro is 2, - * while for the Japanese Yen it's 0. - * In the case of pseudo-currencies, such as IMF Special Drawing Rights, - * -1 is returned. - * - * @return the default number of fraction digits used with this currency - */ + * Gets the default number of fraction digits used with this currency. + * Note that the number of fraction digits is the same as ISO 4217's + * minor unit for the currency. + * For example, the default number of fraction digits for the Euro is 2, + * while for the Japanese Yen it's 0. + * In the case of pseudo-currencies, such as IMF Special Drawing Rights, + * -1 is returned. + * + * @return the default number of fraction digits used with this currency + */ public int getDefaultFractionDigits() { return defaultFractionDigits; } From 19a07cb7dbe771af578160533c7bd6ffca49b28a Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Tue, 23 Feb 2016 09:49:04 +0100 Subject: [PATCH 100/139] 8143410: augment pseudo-code descriptions in MethodHandles API Reviewed-by: psandoz --- .../java/lang/invoke/MethodHandles.java | 91 +++++++++++++++---- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index c7389b63b05..befe2520ec7 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2645,12 +2645,20 @@ assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY * } - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * denotes the return type of both the {@code target} and resulting adapter. + * {@code P}/{@code p} and {@code B}/{@code b} represent the types and values + * of the parameters and arguments that precede and follow the filter position + * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types and + * values of the filtered parameters and arguments; they also represent the + * return types of the {@code filter[i]} handles. The latter accept arguments + * {@code v[i]} of type {@code V[i]}, which also appear in the signature of + * the resulting adapter. *

      {@code
      -     * V target(P... p, A[i]... a[i], B... b);
      +     * T target(P... p, A[i]... a[i], B... b);
            * A[i] filter[i](V[i]);
            * T adapter(P... p, V[i]... v[i], B... b) {
      -     *   return target(p..., f[i](v[i])..., b...);
      +     *   return target(p..., filter[i](v[i])..., b...);
            * }
            * }
      *

      @@ -2762,7 +2770,17 @@ MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3); assertEquals("[top, [[up, down, strange], charm], bottom]", (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom")); * } - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the return type of the {@code target} and resulting adapter. + * {@code V}/{@code v} stand for the return type and value of the + * {@code filter}, which are also found in the signature and arguments of + * the {@code target}, respectively, unless {@code V} is {@code void}. + * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types + * and values preceding and following the collection position, {@code pos}, + * in the {@code target}'s signature. They also turn up in the resulting + * adapter's signature and arguments, where they surround + * {@code B}/{@code b}, which represent the parameter types and arguments + * to the {@code filter} (if any). *

      {@code
            * T target(A...,V,C...);
            * V filter(B...);
      @@ -2780,7 +2798,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
            * // and if the filter has a void return:
            * T target3(A...,C...);
            * void filter3(B...);
      -     * void adapter3(A... a,B... b,C... c) {
      +     * T adapter3(A... a,B... b,C... c) {
            *   filter3(b...);
            *   return target3(a...,c...);
            * }
      @@ -2876,27 +2894,31 @@ System.out.println((String) cat.invokeExact("x", "y")); // xy
       MethodHandle f0 = filterReturnValue(cat, length);
       System.out.println((int) f0.invokeExact("x", "y")); // 2
            * }
      - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, + * {@code T}/{@code t} represent the result type and value of the + * {@code target}; {@code V}, the result type of the {@code filter}; and + * {@code A}/{@code a}, the types and values of the parameters and arguments + * of the {@code target} as well as the resulting adapter. *

      {@code
      -     * V target(A...);
      -     * T filter(V);
      -     * T adapter(A... a) {
      -     *   V v = target(a...);
      -     *   return filter(v);
      +     * T target(A...);
      +     * V filter(T);
      +     * V adapter(A... a) {
      +     *   T t = target(a...);
      +     *   return filter(t);
            * }
            * // and if the target has a void return:
            * void target2(A...);
      -     * T filter2();
      -     * T adapter2(A... a) {
      +     * V filter2();
      +     * V adapter2(A... a) {
            *   target2(a...);
            *   return filter2();
            * }
            * // and if the filter has a void return:
      -     * V target3(A...);
      +     * T target3(A...);
            * void filter3(V);
            * void adapter3(A... a) {
      -     *   V v = target3(a...);
      -     *   filter3(v);
      +     *   T t = target3(a...);
      +     *   filter3(t);
            * }
            * }
      *

      @@ -2979,7 +3001,15 @@ MethodHandle catTrace = foldArguments(cat, trace); // also prints "boo": assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * } - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the result type of the {@code target} and resulting adapter. + * {@code V}/{@code v} represent the type and value of the parameter and argument + * of {@code target} that precedes the folding position; {@code V} also is + * the result type of the {@code combiner}. {@code A}/{@code a} denote the + * types and values of the {@code N} parameters and arguments at the folding + * position. {@code B}/{@code b} represent the types and values of the + * {@code target} parameters and arguments that follow the folded parameters + * and arguments. *

      {@code
            * // there are N arguments in A...
            * T target(V, A[N]..., B...);
      @@ -3040,7 +3070,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * argument and return types, except that the return type
            * of the test must be boolean, and the test is allowed
            * to have fewer arguments than the other two method handles.
      -     * 

      Here is pseudocode for the resulting adapter: + *

      + * Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the uniform result type of the three involved handles; + * {@code A}/{@code a}, the types and values of the {@code target} + * parameters and arguments that are consumed by the {@code test}; and + * {@code B}/{@code b}, those types and values of the {@code target} + * parameters and arguments that are not consumed by the {@code test}. *

      {@code
            * boolean test(A...);
            * T target(A...,B...);
      @@ -3102,7 +3138,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * argument and return types, except that handler may omit trailing arguments
            * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
            * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
      -     * 

      Here is pseudocode for the resulting adapter: + *

      + * Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the return type of the {@code target} and {@code handler}, + * and correspondingly that of the resulting adapter; {@code A}/{@code a}, + * the types and values of arguments to the resulting handle consumed by + * {@code handler}; and {@code B}/{@code b}, those of arguments to the + * resulting handle discarded by {@code handler}. *

      {@code
            * T target(A..., B...);
            * T handler(ExType, A...);
      @@ -3951,7 +3993,16 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
           // also prints "jum":
           assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * }
      - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the result type of the {@code target} and resulting adapter. + * {@code V}/{@code v} represent the type and value of the parameter and argument + * of {@code target} that precedes the folding position; {@code V} also is + * the result type of the {@code combiner}. {@code A}/{@code a} denote the + * types and values of the {@code N} parameters and arguments at the folding + * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types + * and values of the {@code target} parameters and arguments that precede and + * follow the folded parameters and arguments starting at {@code pos}, + * respectively. *

      {@code
            * // there are N arguments in A...
            * T target(Z..., V, A[N]..., B...);
      
      From 4dfed6652630593769bf049be7ac2213ca47b69f Mon Sep 17 00:00:00 2001
      From: Yingqi Lu 
      Date: Tue, 23 Feb 2016 17:41:00 +0000
      Subject: [PATCH 101/139] 6432031: Add support for SO_REUSEPORT
      
      Reviewed-by: alanb, simonis, chegar
      ---
       jdk/make/mapfiles/libnet/mapfile-vers         |  6 +-
       jdk/make/mapfiles/libnio/mapfile-linux        |  3 +-
       jdk/make/mapfiles/libnio/mapfile-macosx       |  3 +-
       jdk/make/mapfiles/libnio/mapfile-solaris      |  3 +-
       .../genconstants/ch/genSocketOptionRegistry.c | 18 ++++-
       .../net/AbstractPlainDatagramSocketImpl.java  | 60 +++++++++++++-
       .../java/net/AbstractPlainSocketImpl.java     | 59 +++++++++++++-
       .../classes/java/net/DatagramSocketImpl.java  |  8 +-
       .../classes/java/net/MulticastSocket.java     | 14 +++-
       .../share/classes/java/net/SocketImpl.java    |  8 +-
       .../share/classes/java/net/SocketOptions.java | 13 +++-
       .../java/net/StandardSocketOptions.java       | 25 +++++-
       .../share/classes/jdk/net/Sockets.java        | 32 +++++++-
       .../AsynchronousServerSocketChannelImpl.java  |  5 +-
       .../nio/ch/AsynchronousSocketChannelImpl.java |  5 +-
       .../sun/nio/ch/DatagramChannelImpl.java       |  5 +-
       .../share/classes/sun/nio/ch/Net.java         | 17 +++-
       .../sun/nio/ch/ServerSocketChannelImpl.java   |  6 +-
       .../classes/sun/nio/ch/SocketChannelImpl.java |  5 +-
       .../java.base/share/native/libnet/net_util.c  | 13 +++-
       .../java.base/share/native/libnet/net_util.h  |  4 +-
       .../java/net/PlainDatagramSocketImpl.java     | 25 +++++-
       .../classes/java/net/PlainSocketImpl.java     | 25 +++++-
       .../native/libnet/PlainDatagramSocketImpl.c   |  6 +-
       .../java.base/unix/native/libnet/SdpSupport.c |  7 +-
       .../java.base/unix/native/libnet/SocketImpl.c | 47 +++++++++++
       .../unix/native/libnet/net_util_md.c          | 22 +++++-
       .../unix/native/libnet/net_util_md.h          | 15 +++-
       jdk/src/java.base/unix/native/libnio/ch/Net.c |  8 +-
       .../unix/native/libnio/ch/nio_util.h          | 14 +++-
       .../net/DualStackPlainDatagramSocketImpl.java | 10 ++-
       .../java/net/DualStackPlainSocketImpl.java    | 10 ++-
       .../classes/java/net/PlainSocketImpl.java     | 23 +++++-
       .../net/TwoStacksPlainDatagramSocketImpl.java |  8 +-
       .../java/net/TwoStacksPlainSocketImpl.java    |  9 ++-
       .../windows/native/libnet/SocketImpl.c        | 47 +++++++++++
       .../windows/native/libnet/net_util_md.c       |  7 +-
       .../windows/native/libnet/net_util_md.h       |  4 +
       .../java.base/windows/native/libnio/ch/Net.c  |  9 ++-
       .../java/net/SocketOption/OptionsTest.java    | 78 +++++++++++++------
       .../Basic.java                                | 12 ++-
       .../AsynchronousSocketChannel/Basic.java      | 12 ++-
       .../DatagramChannel/SocketOptionTests.java    | 23 ++++--
       .../SocketOptionTests.java                    | 11 ++-
       44 files changed, 669 insertions(+), 75 deletions(-)
       create mode 100644 jdk/src/java.base/unix/native/libnet/SocketImpl.c
       create mode 100644 jdk/src/java.base/windows/native/libnet/SocketImpl.c
      
      diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers
      index a37668a8418..82247780181 100644
      --- a/jdk/make/mapfiles/libnet/mapfile-vers
      +++ b/jdk/make/mapfiles/libnet/mapfile-vers
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
       # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       #
       # This code is free software; you can redistribute it and/or modify it
      @@ -87,6 +87,9 @@ SUNWprivate_1.1 {
       		Java_java_net_PlainSocketImpl_socketConnect;
       		Java_java_net_PlainDatagramSocketImpl_getTimeToLive;
       		Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
      +                Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0;
      +                Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0;
      +                Java_jdk_net_Sockets_isReusePortAvailable0;
       		Java_sun_net_PortConfig_getUpper0;
       		Java_sun_net_PortConfig_getLower0;
       		Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
      @@ -112,6 +115,7 @@ SUNWprivate_1.1 {
       		NET_EnableFastTcpLoopback;
       		NET_ThrowNew;
                       ipv6_available;
      +                reuseport_available;
                       initInetAddressIDs;
       
       	local:
      diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux
      index b9b059a80c2..e4563b10c12 100644
      --- a/jdk/make/mapfiles/libnio/mapfile-linux
      +++ b/jdk/make/mapfiles/libnio/mapfile-linux
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
       # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       #
       # This code is free software; you can redistribute it and/or modify it
      @@ -109,6 +109,7 @@ SUNWprivate_1.1 {
       		Java_sun_nio_ch_Net_setIntOption0;
                       Java_sun_nio_ch_Net_initIDs;
       		Java_sun_nio_ch_Net_isIPv6Available0;
      +                Java_sun_nio_ch_Net_isReusePortAvailable0;
       		Java_sun_nio_ch_Net_joinOrDrop4;
       		Java_sun_nio_ch_Net_blockOrUnblock4;
       		Java_sun_nio_ch_Net_joinOrDrop6;
      diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx
      index 6e4a7fb594c..daee0371e3c 100644
      --- a/jdk/make/mapfiles/libnio/mapfile-macosx
      +++ b/jdk/make/mapfiles/libnio/mapfile-macosx
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
       # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       #
       # This code is free software; you can redistribute it and/or modify it
      @@ -102,6 +102,7 @@ SUNWprivate_1.1 {
       		Java_sun_nio_ch_Net_setIntOption0;
                       Java_sun_nio_ch_Net_initIDs;
       		Java_sun_nio_ch_Net_isIPv6Available0;
      +                Java_sun_nio_ch_Net_isReusePortAvailable0;
       		Java_sun_nio_ch_Net_joinOrDrop4;
       		Java_sun_nio_ch_Net_blockOrUnblock4;
       		Java_sun_nio_ch_Net_joinOrDrop6;
      diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris
      index 6834bd221d4..a1e0d99b0e6 100644
      --- a/jdk/make/mapfiles/libnio/mapfile-solaris
      +++ b/jdk/make/mapfiles/libnio/mapfile-solaris
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
       # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       #
       # This code is free software; you can redistribute it and/or modify it
      @@ -97,6 +97,7 @@ SUNWprivate_1.1 {
       		Java_sun_nio_ch_Net_setIntOption0;
                       Java_sun_nio_ch_Net_initIDs;
       		Java_sun_nio_ch_Net_isIPv6Available0;
      +                Java_sun_nio_ch_Net_isReusePortAvailable0;
       		Java_sun_nio_ch_Net_joinOrDrop4;
       		Java_sun_nio_ch_Net_blockOrUnblock4;
       		Java_sun_nio_ch_Net_joinOrDrop6;
      diff --git a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
      index 41bd5484ab7..aab692f1f19 100644
      --- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
      +++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
        * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
        *
        * This code is free software; you can redistribute it and/or modify it
      @@ -34,6 +34,21 @@
       #include 
       #endif
       
      +/* Defines SO_REUSEPORT */
      +#if !defined(SO_REUSEPORT)
      +#ifdef _WIN32
      +#define SO_REUSEPORT 0
      +#elif __linux__
      +#define SO_REUSEPORT 15
      +#elif __solaris__
      +#define SO_REUSEPORT 0x100e
      +#elif defined(AIX) || defined(MACOSX)
      +#define SO_REUSEPORT 0x0200
      +#else
      +#define SO_REUSEPORT 0
      +#endif
      +#endif
      +
       /**
        * Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level
        * socket options to the platform specific level and option.
      @@ -102,6 +117,7 @@ int main(int argc, const char* argv[]) {
           emit_unspec("StandardSocketOptions.SO_SNDBUF",    SOL_SOCKET, SO_SNDBUF);
           emit_unspec("StandardSocketOptions.SO_RCVBUF",    SOL_SOCKET, SO_RCVBUF);
           emit_unspec("StandardSocketOptions.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR);
      +    emit_unspec("StandardSocketOptions.SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT);
           emit_unspec("StandardSocketOptions.TCP_NODELAY",  IPPROTO_TCP, TCP_NODELAY);
       
           emit_inet("StandardSocketOptions.IP_TOS",            IPPROTO_IP,     IP_TOS);
      diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
      index 1f9eba1300e..7a9b7fc17ed 100644
      --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
      +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
        * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
        *
        * This code is free software; you can redistribute it and/or modify it
      @@ -28,6 +28,9 @@ import java.io.FileDescriptor;
       import java.io.IOException;
       import java.security.AccessController;
       import sun.net.ResourceManager;
      +import java.util.Set;
      +import java.util.HashSet;
      +import java.util.Collections;
       
       /**
        * Abstract datagram and multicast socket implementation base class.
      @@ -70,6 +73,45 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
                   });
           }
       
      +    private static volatile boolean checkedReusePort;
      +    private static volatile boolean isReusePortAvailable;
      +
      +    /**
      +     * Tells whether SO_REUSEPORT is supported.
      +     */
      +    static boolean isReusePortAvailable() {
      +        if (!checkedReusePort) {
      +            isReusePortAvailable = isReusePortAvailable0();
      +            checkedReusePort = true;
      +        }
      +        return isReusePortAvailable;
      +    }
      +
      +    private static volatile Set> socketOptions;
      +
      +    /**
      +     * Returns a set of SocketOptions supported by this impl
      +     * and by this impl's socket (Socket or ServerSocket)
      +     *
      +     * @return a Set of SocketOptions
      +     */
      +    @Override
      +    protected Set> supportedOptions() {
      +        Set> options = socketOptions;
      +        if (options == null) {
      +            if (isReusePortAvailable()) {
      +                options = new HashSet<>();
      +                options.addAll(super.supportedOptions());
      +                options.add(StandardSocketOptions.SO_REUSEPORT);
      +                options = Collections.unmodifiableSet(options);
      +            } else {
      +                options = super.supportedOptions();
      +            }
      +            socketOptions = options;
      +        }
      +        return options;
      +    }
      +
           /**
            * Creates a datagram socket
            */
      @@ -303,6 +345,14 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
                    if (o == null || !(o instanceof Boolean))
                        throw new SocketException("bad argument for IP_MULTICAST_LOOP");
                    break;
      +         case SO_REUSEPORT:
      +             if (o == null || !(o instanceof Boolean)) {
      +                 throw new SocketException("bad argument for SO_REUSEPORT");
      +             }
      +             if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
      +                 throw new UnsupportedOperationException("unsupported option");
      +             }
      +             break;
                default:
                    throw new SocketException("invalid option: " + optID);
                }
      @@ -343,6 +393,13 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
                       result = socketGetOption(optID);
                       break;
       
      +            case SO_REUSEPORT:
      +                if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
      +                    throw new UnsupportedOperationException("unsupported option");
      +                }
      +                result = socketGetOption(optID);
      +                break;
      +
                   default:
                       throw new SocketException("invalid option: " + optID);
               }
      @@ -364,4 +421,5 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
           }
       
           abstract int dataAvailable();
      +    private static native boolean isReusePortAvailable0();
       }
      diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
      index 8841e4fe724..c9afa2657a2 100644
      --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
      +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
        * 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,6 +33,9 @@ import java.io.FileDescriptor;
       import sun.net.ConnectionResetException;
       import sun.net.NetHooks;
       import sun.net.ResourceManager;
      +import java.util.Set;
      +import java.util.HashSet;
      +import java.util.Collections;
       
       /**
        * Default Socket Implementation. This implementation does
      @@ -87,6 +90,45 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
                   });
           }
       
      +    private static volatile boolean checkedReusePort;
      +    private static volatile boolean isReusePortAvailable;
      +
      +    /**
      +     * Tells whether SO_REUSEPORT is supported.
      +     */
      +    static boolean isReusePortAvailable() {
      +        if (!checkedReusePort) {
      +            isReusePortAvailable = isReusePortAvailable0();
      +            checkedReusePort = true;
      +        }
      +        return isReusePortAvailable;
      +    }
      +
      +    private static volatile Set> socketOptions;
      +
      +   /**
      +    * Returns a set of SocketOptions supported by this impl
      +    * and by this impl's socket (Socket or ServerSocket)
      +    *
      +    * @return a Set of SocketOptions
      +    */
      +    @Override
      +    protected Set> supportedOptions() {
      +        Set> options = socketOptions;
      +        if (options == null) {
      +            if (isReusePortAvailable()) {
      +                options = new HashSet<>();
      +                options.addAll(super.supportedOptions());
      +                options.add(StandardSocketOptions.SO_REUSEPORT);
      +                options = Collections.unmodifiableSet(options);
      +            } else {
      +                options = super.supportedOptions();
      +            }
      +            socketOptions = options;
      +        }
      +        return options;
      +    }
      +
           /**
            * Creates a socket with a boolean that specifies whether this
            * is a stream socket (true) or an unconnected UDP socket (false).
      @@ -269,6 +311,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
                       throw new SocketException("bad parameter for SO_REUSEADDR");
                   on = ((Boolean)val).booleanValue();
                   break;
      +        case SO_REUSEPORT:
      +            if (val == null || !(val instanceof Boolean))
      +                throw new SocketException("bad parameter for SO_REUSEPORT");
      +            if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT))
      +                throw new UnsupportedOperationException("unsupported option");
      +            on = ((Boolean)val).booleanValue();
      +            break;
               default:
                   throw new SocketException("unrecognized TCP option: " + opt);
               }
      @@ -326,6 +375,12 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
               case SO_KEEPALIVE:
                   ret = socketGetOption(opt, null);
                   return Boolean.valueOf(ret != -1);
      +        case SO_REUSEPORT:
      +            if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
      +                throw new UnsupportedOperationException("unsupported option");
      +            }
      +            ret = socketGetOption(opt, null);
      +            return Boolean.valueOf(ret != -1);
               // should never get here
               default:
                   return null;
      @@ -723,4 +778,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
       
           public static final int SHUT_RD = 0;
           public static final int SHUT_WR = 1;
      +
      +    private static native boolean isReusePortAvailable0();
       }
      diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
      index 97526bc3712..5621ea3a608 100644
      --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
      +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
        * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
        *
        * This code is free software; you can redistribute it and/or modify it
      @@ -287,6 +287,9 @@ public abstract class DatagramSocketImpl implements SocketOptions {
                   setOption(SocketOptions.SO_RCVBUF, value);
               } else if (name == StandardSocketOptions.SO_REUSEADDR) {
                   setOption(SocketOptions.SO_REUSEADDR, value);
      +        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
      +            supportedOptions().contains(name)) {
      +            setOption(SocketOptions.SO_REUSEPORT, value);
               } else if (name == StandardSocketOptions.IP_TOS) {
                   setOption(SocketOptions.IP_TOS, value);
               } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
      @@ -329,6 +332,9 @@ public abstract class DatagramSocketImpl implements SocketOptions {
                   return (T) getOption(SocketOptions.SO_RCVBUF);
               } else if (name == StandardSocketOptions.SO_REUSEADDR) {
                   return (T) getOption(SocketOptions.SO_REUSEADDR);
      +        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
      +            supportedOptions().contains(name)) {
      +            return (T) getOption(SocketOptions.SO_REUSEPORT);
               } else if (name == StandardSocketOptions.IP_TOS) {
                   return (T) getOption(SocketOptions.IP_TOS);
               } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
      diff --git a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java
      index 77c6e198ab0..365092b1e07 100644
      --- a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java
      +++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
        * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
        *
        * This code is free software; you can redistribute it and/or modify it
      @@ -98,7 +98,11 @@ class MulticastSocket extends DatagramSocket {
            * 

      * When the socket is created the * {@link DatagramSocket#setReuseAddress(boolean)} method is - * called to enable the SO_REUSEADDR socket option. + * called to enable the SO_REUSEADDR socket option. When + * {@link StandardSocketOptions#SO_REUSEPORT SO_REUSEPORT} is + * supported then + * {@link DatagramSocketImpl#setOption(SocketOption, Object)} + * is called to enable the socket option. * * @exception IOException if an I/O exception occurs * while creating the MulticastSocket @@ -106,6 +110,7 @@ class MulticastSocket extends DatagramSocket { * {@code checkListen} method doesn't allow the operation. * @see SecurityManager#checkListen * @see java.net.DatagramSocket#setReuseAddress(boolean) + * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object) */ public MulticastSocket() throws IOException { this(new InetSocketAddress(0)); @@ -167,6 +172,11 @@ class MulticastSocket extends DatagramSocket { // Enable SO_REUSEADDR before binding setReuseAddress(true); + // Enable SO_REUSEPORT if supported before binding + if (supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + this.setOption(StandardSocketOptions.SO_REUSEPORT, true); + } + if (bindaddr != null) { try { bind(bindaddr); diff --git a/jdk/src/java.base/share/classes/java/net/SocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocketImpl.java index eef92f30b6e..7a30173a597 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -386,6 +386,9 @@ public abstract class SocketImpl implements SocketOptions { setOption(SocketOptions.SO_RCVBUF, value); } else if (name == StandardSocketOptions.SO_REUSEADDR) { setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + setOption(SocketOptions.SO_REUSEPORT, value); } else if (name == StandardSocketOptions.SO_LINGER && (getSocket() != null)) { setOption(SocketOptions.SO_LINGER, value); @@ -426,6 +429,9 @@ public abstract class SocketImpl implements SocketOptions { return (T)getOption(SocketOptions.SO_RCVBUF); } else if (name == StandardSocketOptions.SO_REUSEADDR) { return (T)getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + return (T)getOption(SocketOptions.SO_REUSEPORT); } else if (name == StandardSocketOptions.SO_LINGER && (getSocket() != null)) { return (T)getOption(SocketOptions.SO_LINGER); diff --git a/jdk/src/java.base/share/classes/java/net/SocketOptions.java b/jdk/src/java.base/share/classes/java/net/SocketOptions.java index c846bbb9b12..fbfb81eca1a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,6 +170,17 @@ public interface SocketOptions { @Native public static final int SO_REUSEADDR = 0x04; + /** Sets SO_REUSEPORT for a socket. This option enables and disables + * the ability to have multiple sockets listen to the same address + * and port. + *

      + * Valid for: SocketImpl, DatagramSocketImpl + * + * @since 9 + * @see StandardSocketOptions#SO_REUSEPORT + */ + @Native public static final int SO_REUSEPORT = 0x0E; + /** * Sets SO_BROADCAST for a socket. This option enables and disables * the ability of the process to send broadcast messages. It is supported diff --git a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java index 7fdd5f075d6..ae47845fae3 100644 --- a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -186,6 +186,29 @@ public final class StandardSocketOptions { public static final SocketOption SO_REUSEADDR = new StdSocketOption("SO_REUSEADDR", Boolean.class); + /** + * Re-use port. + * + *

      The value of this socket option is a {@code Boolean} that represents + * whether the option is enabled or disabled. The exact semantics of this + * socket option are socket type and system dependent. + * + *

      In the case of stream-oriented sockets, this socket option usually allows + * multiple listening sockets to be bound to both same address + * and same port. + * + *

      For datagram-oriented sockets the socket option usually allows + * multiple UDP sockets to be bound to the same address and port. + * + *

      An implementation allows this socket option to be set before the + * socket is bound or connected. Changing the value of this socket option + * after the socket is bound has no effect. + * + * @since 9 + */ + public static final SocketOption SO_REUSEPORT = + new StdSocketOption("SO_REUSEPORT", Boolean.class); + /** * Linger on close if data is present. * diff --git a/jdk/src/java.base/share/classes/jdk/net/Sockets.java b/jdk/src/java.base/share/classes/jdk/net/Sockets.java index 1ba53f29a15..a8b78b044d8 100644 --- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java +++ b/jdk/src/java.base/share/classes/jdk/net/Sockets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,9 +251,23 @@ public class Sockets { } } + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; + + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + private static void initOptionSets() { boolean flowsupported = ExtendedOptionsImpl.flowSupported(); - + boolean reuseportsupported = isReusePortAvailable(); // Socket Set> set = new HashSet<>(); @@ -261,6 +275,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.TCP_NODELAY); @@ -275,6 +292,9 @@ public class Sockets { set = new HashSet<>(); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); @@ -285,6 +305,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); @@ -298,6 +321,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); @@ -308,4 +334,6 @@ public class Sockets { set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); } + + private static native boolean isReusePortAvailable0(); } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java index 8ed2c9f1317..39b19b42204 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,6 +231,9 @@ abstract class AsynchronousServerSocketChannelImpl HashSet> set = new HashSet<>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 3122b96a29f..36b3c1b7ab9 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -508,6 +508,9 @@ abstract class AsynchronousSocketChannelImpl set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.TCP_NODELAY); if (ExtendedOptionsImpl.flowSupported()) { set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 7eb987991c9..77d14619222 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -298,6 +298,9 @@ class DatagramChannelImpl set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_BROADCAST); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java index 27c46a9ca2c..062ce35468e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 +56,8 @@ public class Net { private static volatile boolean checkedIPv6; private static volatile boolean isIPv6Available; + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; /** * Tells whether dual-IPv4/IPv6 sockets should be used. @@ -68,6 +70,17 @@ public class Net { return isIPv6Available; } + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + /** * Returns true if exclusive binding is on */ @@ -389,6 +402,8 @@ public class Net { private static native boolean isIPv6Available0(); + private static native boolean isReusePortAvailable0(); + /* * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS */ diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 2a427f1a352..9cfe7c43c4d 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 +33,6 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; - /** * An implementation of ServerSocketChannels */ @@ -185,6 +184,9 @@ class ServerSocketChannelImpl HashSet> set = new HashSet<>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); return Collections.unmodifiableSet(set); } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index c4965e1111b..c4644920c3e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,6 +234,9 @@ class SocketChannelImpl set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.TCP_NODELAY); // additional options required by socket adaptor diff --git a/jdk/src/java.base/share/native/libnet/net_util.c b/jdk/src/java.base/share/native/libnet/net_util.c index e94903fd720..c2d4b002b04 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.c +++ b/jdk/src/java.base/share/native/libnet/net_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,14 +29,21 @@ #include "net_util.h" int IPv6_supported() ; +int reuseport_supported() ; static int IPv6_available; +static int REUSEPORT_available; JNIEXPORT jint JNICALL ipv6_available() { return IPv6_available ; } +JNIEXPORT jint JNICALL reuseport_available() +{ + return REUSEPORT_available; +} + JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { @@ -45,7 +52,6 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) jmethodID mid; jstring s; jint preferIPv4Stack; - if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) { return JNI_EVERSION; /* JNI version not supported */ } @@ -64,6 +70,9 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) supporting socket APIs are available */ IPv6_available = IPv6_supported() & (!preferIPv4Stack); + + /* check if SO_REUSEPORT is supported on this platform */ + REUSEPORT_available = reuseport_supported(); platformInit(); parseExclusiveBindProperty(env); diff --git a/jdk/src/java.base/share/native/libnet/net_util.h b/jdk/src/java.base/share/native/libnet/net_util.h index f6b29297ecf..1d7b2a2c51e 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.h +++ b/jdk/src/java.base/share/native/libnet/net_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,6 +131,8 @@ jfieldID NET_GetFileDescriptorID(JNIEnv *env); JNIEXPORT jint JNICALL ipv6_available() ; +JNIEXPORT jint JNICALL reuseport_available() ; + void NET_AllocSockaddr(struct sockaddr **him, int *len); diff --git a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java index 31715d40c82..f7c65931613 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,15 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl protected void setOption(SocketOption name, T value) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + super.setOption(name, value); + } else { + if (supportedOptions().contains(name)) { + super.setOption(name, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } else { if (!flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -62,7 +70,15 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + return super.getOption(name); + } else { + if (supportedOptions().contains(name)) { + return super.getOption(name); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } if (!flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -87,6 +103,9 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } protected void socketSetOption(int opt, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } try { socketSetOption0(opt, val); } catch (SocketException se) { diff --git a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java index 272130bd6b9..2ec573ea5a9 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl protected void setOption(SocketOption name, T value) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + super.setOption(name, value); + } else { + if (supportedOptions().contains(name)) { + super.setOption(name, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } else { if (getSocket() == null || !flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -76,7 +84,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + return super.getOption(name); + } else { + if (supportedOptions().contains(name)) { + return super.getOption(name); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } if (getSocket() == null || !flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -101,6 +117,9 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } try { socketSetOption0(opt, b, val); } catch (SocketException se) { diff --git a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c index e6f18428769..034040baf83 100644 --- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c +++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1392,6 +1392,7 @@ Java_java_net_PlainDatagramSocketImpl_socketSetOption0(JNIEnv *env, } case java_net_SocketOptions_SO_REUSEADDR: + case java_net_SocketOptions_SO_REUSEPORT: case java_net_SocketOptions_SO_BROADCAST: { jclass cls; @@ -1769,6 +1770,9 @@ Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, case java_net_SocketOptions_SO_REUSEADDR: return createBoolean(env, optval.i); + case java_net_SocketOptions_SO_REUSEPORT: + return createBoolean(env, optval.i); + case java_net_SocketOptions_SO_SNDBUF: case java_net_SocketOptions_SO_RCVBUF: case java_net_SocketOptions_IP_TOS: diff --git a/jdk/src/java.base/unix/native/libnet/SdpSupport.c b/jdk/src/java.base/unix/native/libnet/SdpSupport.c index be8c46464fa..1fe5353fcd6 100644 --- a/jdk/src/java.base/unix/native/libnet/SdpSupport.c +++ b/jdk/src/java.base/unix/native/libnet/SdpSupport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,6 +108,11 @@ Java_sun_net_sdp_SdpSupport_convert0(JNIEnv *env, jclass cls, int fd) len = sizeof(arg); if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len); +#ifdef SO_REUSEPORT + len = sizeof(arg); + if (getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, &len) == 0) + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, len); +#endif len = sizeof(arg); if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0) setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len); diff --git a/jdk/src/java.base/unix/native/libnet/SocketImpl.c b/jdk/src/java.base/unix/native/libnet/SocketImpl.c new file mode 100644 index 00000000000..3427b0ef405 --- /dev/null +++ b/jdk/src/java.base/unix/native/libnet/SocketImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +#include "net_util.h" + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.c b/jdk/src/java.base/unix/native/libnet/net_util_md.c index f5645699d29..abad413e39c 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.c +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -439,6 +439,25 @@ jint IPv6_supported() } #endif /* DONT_ENABLE_IPV6 */ +jint reuseport_supported() +{ + /* Do a simple dummy call, and try to figure out from that */ + int one = 1; + int rv, s; + s = socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) { + return JNI_FALSE; + } + rv = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void *)&one, sizeof(one)); + if (rv != 0) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + return rv; +} + void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, const char* hostname, int gai_error) @@ -1014,6 +1033,7 @@ NET_MapSocketOption(jint cmd, int *level, int *optname) { { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE }, { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR }, + { java_net_SocketOptions_SO_REUSEPORT, SOL_SOCKET, SO_REUSEPORT }, { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST }, { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS }, { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF }, diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.h b/jdk/src/java.base/unix/native/libnet/net_util_md.h index 31ed3f808eb..f440bd8ae6a 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.h +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,19 @@ void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, #define NET_WAIT_WRITE 0x02 #define NET_WAIT_CONNECT 0x04 +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif + jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout); /************************************************************************ diff --git a/jdk/src/java.base/unix/native/libnio/ch/Net.c b/jdk/src/java.base/unix/native/libnio/ch/Net.c index 1010355bb76..a4032d69652 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/Net.c +++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,6 +161,12 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return (ipv6_available()) ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return -1; diff --git a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h index 441ea20cc7c..c769dfbd49c 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h +++ b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,18 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif /* NIO utility procedures */ diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 88a7ddcfdb0..8f464ddfd07 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -167,6 +167,11 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl int optionValue = 0; + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } + switch(opt) { case IP_TOS : case SO_RCVBUF : @@ -200,6 +205,9 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } if (opt == SO_REUSEADDR && reuseAddressEmulated) return isReuseAddress; + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) + throw new UnsupportedOperationException("unsupported option"); int value = socketGetIntOption(nativefd, opt); Object returnValue = null; diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java index 6792a411842..3d681db1dd6 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,6 +181,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl if (opt == SO_TIMEOUT) { // timeout implemented through select. return; } + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } int optionValue = 0; @@ -224,6 +228,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl localAddress(nativefd, (InetAddressContainer)iaContainerObj); return 0; // return value doesn't matter. } + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } // SO_REUSEADDR emulated when using exclusive bind if (opt == SO_REUSEADDR && exclusiveBind) diff --git a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java index 938d995593b..259a39ac195 100644 --- a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,10 +173,18 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } public void setOption(int opt, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } impl.setOption(opt, val); } public Object getOption(int opt) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } return impl.getOption(opt); } @@ -332,14 +340,27 @@ class PlainSocketImpl extends AbstractPlainSocketImpl void socketSetOption(int cmd, boolean on, Object value) throws SocketException { + if (cmd == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } impl.socketSetOption(cmd, on, value); } int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } return impl.socketGetOption(opt, iaContainerObj); } void socketSendUrgentData(int data) throws IOException { impl.socketSendUrgentData(data); } + + static boolean isReusePortAvailable() { + // SO_REUSEPORT is not supported on Windows. + return false; + } } diff --git a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java index 9bdb8d5c6e1..7198b49671e 100644 --- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,6 +130,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl return socketLocalAddress(family); } else if (optID == SO_REUSEADDR && reuseAddressEmulated) { return isReuseAddress; + } else if (optID == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else { return super.getOption(optID); } @@ -142,6 +145,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl // socket already bound, emulate reuseAddressEmulated = true; isReuseAddress = (Boolean)val; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else { socketNativeSetOption(opt, val); } diff --git a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java index a8be4000d93..4f0b132520e 100644 --- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,6 +128,9 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl } else if (opt == SO_REUSEADDR && exclusiveBind) { // SO_REUSEADDR emulated when using exclusive bind return isReuseAddress; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else return super.getOption(opt); } @@ -144,6 +147,10 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl // SO_REUSEADDR emulated when using exclusive bind if (opt == SO_REUSEADDR && exclusiveBind) isReuseAddress = on; + else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } else socketNativeSetOption(opt, on, value); } diff --git a/jdk/src/java.base/windows/native/libnet/SocketImpl.c b/jdk/src/java.base/windows/native/libnet/SocketImpl.c new file mode 100644 index 00000000000..8e5745de8d3 --- /dev/null +++ b/jdk/src/java.base/windows/native/libnet/SocketImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c index 8a0f5c15275..4868201c1f3 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.c +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,6 +242,11 @@ jint IPv6_supported() return JNI_TRUE; } +jint reuseport_supported() +{ + /* SO_REUSEPORT is not supported onn Windows */ + return JNI_FALSE; +} /* * Return the default TOS value */ diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.h b/jdk/src/java.base/windows/native/libnet/net_util_md.h index db6971616bf..5ac48046f3b 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.h +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h @@ -54,6 +54,9 @@ #else +/*SO_REUSEPORT is not supported on Windows, define it to 0*/ +#define SO_REUSEPORT 0 + /* Retain this code a little longer to support building in * old environments. _MSC_VER is defined as: * 1200 for MSVC++ 6.0 @@ -353,3 +356,4 @@ JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP (JNIEnv *env, jclass cls, jstring name, jint index); + diff --git a/jdk/src/java.base/windows/native/libnio/ch/Net.c b/jdk/src/java.base/windows/native/libnio/ch/Net.c index 12f3c190c49..c7702006d27 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/Net.c +++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,6 +93,13 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return ipv6_available() ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return 1; diff --git a/jdk/test/java/net/SocketOption/OptionsTest.java b/jdk/test/java/net/SocketOption/OptionsTest.java index 947d784aa9d..5b109d533ac 100644 --- a/jdk/test/java/net/SocketOption/OptionsTest.java +++ b/jdk/test/java/net/SocketOption/OptionsTest.java @@ -54,6 +54,7 @@ public class OptionsTest { Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -61,6 +62,7 @@ public class OptionsTest { static Test[] serverSocketTests = new Test[] { Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -68,6 +70,7 @@ public class OptionsTest { Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -97,15 +100,19 @@ public class OptionsTest { Socket c = new Socket("127.0.0.1", srv.getLocalPort()); Socket s = srv.accept(); ) { + Set> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) { return Boolean.valueOf(socket.getKeepAlive()); @@ -183,6 +200,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.SO_LINGER)) { return Integer.valueOf(socket.getSoLinger()); } else if (option.equals(StandardSocketOptions.IP_TOS)) { @@ -194,10 +213,15 @@ public class OptionsTest { } } else if (type.equals(ServerSocket.class)) { ServerSocket socket = (ServerSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); + if (option.equals(StandardSocketOptions.SO_RCVBUF)) { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(jdk.net.Sockets.getOption( socket, StandardSocketOptions.IP_TOS)); @@ -206,6 +230,8 @@ public class OptionsTest { } } else if (type.equals(DatagramSocket.class)) { DatagramSocket socket = (DatagramSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_SNDBUF)) { return Integer.valueOf(socket.getSendBufferSize()); @@ -213,6 +239,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else { @@ -221,6 +249,8 @@ public class OptionsTest { } else if (type.equals(MulticastSocket.class)) { MulticastSocket socket = (MulticastSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_SNDBUF)) { return Integer.valueOf(socket.getSendBufferSize()); @@ -228,6 +258,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) { diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java index 753629f8e1b..c3450df7d23 100644 --- a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * 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,8 +141,11 @@ public class Basic { try { // check supported options Set> options = ch.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_REUSEPORT) && reuseport) + throw new RuntimeException("SO_REUSEPORT should be supported"); if (!options.contains(SO_RCVBUF)) throw new RuntimeException("SO_RCVBUF should be supported"); @@ -156,6 +159,13 @@ public class Basic { checkOption(ch, SO_REUSEADDR, true); ch.setOption(SO_REUSEADDR, false); checkOption(ch, SO_REUSEADDR, false); + + if (reuseport) { + ch.setOption(SO_REUSEPORT, true); + checkOption(ch, SO_REUSEPORT, true); + ch.setOption(SO_REUSEPORT, false); + checkOption(ch, SO_REUSEPORT, false); + } } finally { ch.close(); } diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index 23d9eb36e4e..c833735eb0f 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.io.Closeable; import java.io.IOException; +import java.util.Set; public class Basic { static final Random rand = new Random(); @@ -165,6 +166,15 @@ public class Basic { // read others (can't check as actual value is implementation dependent) ch.getOption(SO_RCVBUF); ch.getOption(SO_SNDBUF); + + Set> options = ch.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); + if (reuseport) { + if (ch.getOption(SO_REUSEPORT)) + throw new RuntimeException("Default of SO_REUSEPORT should be 'false'"); + if (!ch.setOption(SO_REUSEPORT, true).getOption(SO_REUSEPORT)) + throw new RuntimeException("SO_REUSEPORT did not change"); + } } } diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index bc7146cc982..40aef3282ac 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,17 @@ public class SocketOptionTests { // check supported options Set> options = dc.supportedOptions(); - List> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, - SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, - IP_MULTICAST_LOOP); + boolean reuseport = options.contains(SO_REUSEPORT); + List> expected; + if (reuseport) { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, + SO_REUSEADDR, SO_REUSEPORT, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, + IP_MULTICAST_TTL, IP_MULTICAST_LOOP); + } else { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, + SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, + IP_MULTICAST_LOOP); + } for (SocketOption opt: expected) { if (!options.contains(opt)) throw new RuntimeException(opt.name() + " should be supported"); @@ -83,7 +91,12 @@ public class SocketOptionTests { checkOption(dc, SO_REUSEADDR, true); dc.setOption(SO_REUSEADDR, false); checkOption(dc, SO_REUSEADDR, false); - + if (reuseport) { + dc.setOption(SO_REUSEPORT, true); + checkOption(dc, SO_REUSEPORT, true); + dc.setOption(SO_REUSEPORT, false); + checkOption(dc, SO_REUSEPORT, false); + } // bind socket dc.bind(new InetSocketAddress(0)); diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index a7756989290..0a3aa9dee32 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * 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,8 +49,11 @@ public class SocketOptionTests { // check supported options Set> options = ssc.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_REUSEPORT) && reuseport) + throw new RuntimeException("SO_REUSEPORT should be supported"); if (!options.contains(SO_RCVBUF)) throw new RuntimeException("SO_RCVBUF should be supported"); @@ -64,6 +67,12 @@ public class SocketOptionTests { checkOption(ssc, SO_REUSEADDR, true); ssc.setOption(SO_REUSEADDR, false); checkOption(ssc, SO_REUSEADDR, false); + if (reuseport) { + ssc.setOption(SO_REUSEPORT, true); + checkOption(ssc, SO_REUSEPORT, true); + ssc.setOption(SO_REUSEPORT, false); + checkOption(ssc, SO_REUSEPORT, false); + } // NullPointerException try { From e9d44ad2ca2a253a7784c01c1931474e5649e065 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 23 Feb 2016 10:51:37 -0800 Subject: [PATCH 102/139] 8150434: Remove redundant "jdk_localedata" from the CLDR locale data meta info class name Reviewed-by: mchung --- .../build/tools/cldrconverter/ResourceBundleGenerator.java | 5 +---- .../services/sun.util.locale.provider.LocaleDataMetaInfo | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index c2f16e823cf..500cf2b10e4 100644 --- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -248,10 +248,7 @@ class ResourceBundleGenerator implements BundleGenerator { dir.mkdirs(); } String className = - (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : - "CLDRLocaleDataMetaInfo_" + - CLDRConverter.DESTINATION_DIR.substring(CLDRConverter.DESTINATION_DIR.lastIndexOf('/')+1) - .replaceAll("\\.", "_")); + (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : "CLDRLocaleDataMetaInfo"); File file = new File(dir, className + ".java"); if (!file.exists()) { file.createNewFile(); diff --git a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo index b2a0b3ad6c7..076f3b15265 100644 --- a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo +++ b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo @@ -1,2 +1,2 @@ sun.util.resources.provider.NonBaseLocaleDataMetaInfo -sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo_jdk_localedata +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo From aa585fa3cf5db420e14588d8c58730dab1e16bf0 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 23 Feb 2016 17:19:28 -0500 Subject: [PATCH 103/139] 8150337: sun/misc/SunMiscSignalTest.java failed intermittently Correct test to allow for signals to be ignored Reviewed-by: bpb --- .../classes/jdk/internal/misc/Signal.java | 5 ++ jdk/test/sun/misc/SunMiscSignalTest.java | 46 ++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java index 92adbbe295e..0002fdcde93 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java @@ -279,6 +279,11 @@ public final class Signal { public void handle(Signal sig) { throw new UnsupportedOperationException("invoking native signal handle not supported"); } + + public String toString() { + return this == SIG_DFL ? "SIG_DFL" : + (this == SIG_IGN ? "SIG_IGN" : super.toString()); + } } } diff --git a/jdk/test/sun/misc/SunMiscSignalTest.java b/jdk/test/sun/misc/SunMiscSignalTest.java index 4179b000b85..3dbab4f6cc0 100644 --- a/jdk/test/sun/misc/SunMiscSignalTest.java +++ b/jdk/test/sun/misc/SunMiscSignalTest.java @@ -180,6 +180,12 @@ public class SunMiscSignalTest { return newArray; } + // Return true if the signal is one of the shutdown signals known to the VM + private static boolean isShutdownSignal(Signal signal) { + String name = signal.getName(); + return name.equals("INT") || name.equals("HUP") || name.equals("TERM"); + } + /** * Quick verification of supported signals using sun.misc.Signal. * @@ -201,14 +207,24 @@ public class SunMiscSignalTest { Assert.assertEquals(signal.toString(), "SIG" + name, "toString() mismatch, "); try { - SignalHandler old = Signal.handle(signal, h); + orig = Signal.handle(signal, h); + printf("oldHandler: %s%n", orig); Assert.assertEquals(CanRegister.YES, register, "Unexpected handle succeeded " + name); try { Signal.raise(signal); Assert.assertEquals(CanRaise.YES, raise, "Unexpected raise success for " + name); Invoked inv = h.semaphore().tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS) ? Invoked.YES : Invoked.NO; - Assert.assertEquals(inv, invoked, "handler not invoked;"); + if (!isShutdownSignal(signal)) { + // Normal case + Assert.assertEquals(inv, invoked, "handler not invoked;"); + } else { + if (orig == SignalHandler.SIG_IGN) { + Assert.assertEquals(inv, Invoked.NO, "handler should not be invoked"); + } else { + Assert.assertEquals(inv, invoked, "handler not invoked;"); + } + } } catch (IllegalArgumentException uoe3) { Assert.assertNotEquals(CanRaise.YES, raise, "raise failed for " + name + ": " + uoe3.getMessage()); @@ -270,14 +286,22 @@ public class SunMiscSignalTest { } // Test expected exception when raising a signal when no handler defined - @Test(expectedExceptions = IllegalArgumentException.class) + @Test static void testRaiseNoConsumer() { Signal signal = new Signal("INT"); SignalHandler orig = null; try { - Signal.handle(signal, SignalHandler.SIG_DFL); + orig = Signal.handle(signal, SignalHandler.SIG_DFL); + printf("oldHandler: %s%n", orig); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for TERM means it cannot be handled + return; + } Signal.raise(signal); - } finally { + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException iae) { + printf("IAE message: %s%n", iae.getMessage()); + } finally { // Restore original signal handler if (orig != null && signal != null) { Signal.handle(signal, orig); @@ -296,7 +320,13 @@ public class SunMiscSignalTest { } Handler handler = new Handler(); Signal signal = new Signal("INT"); - Signal.handle(signal, handler); + SignalHandler orig = Signal.handle(signal, handler); + printf("oldHandler: %s%n", orig); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for INT means it cannot be handled + return; + } + Signal.raise(signal); boolean handled = handler.semaphore() .tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS); @@ -332,6 +362,10 @@ public class SunMiscSignalTest { Handler h1 = new Handler(); Handler h2 = new Handler(); SignalHandler orig = Signal.handle(signal, h1); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for TERM means it cannot be handled + return; + } try { SignalHandler prev = Signal.handle(signal, h2); From c542850197c0325cbe02a71b37c1161637673690 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 24 Feb 2016 00:14:23 +0100 Subject: [PATCH 104/139] 8150456: jdk 9 nightly build fails on Windows 32 bit Reviewed-by: tbell, ihse --- jdk/make/lib/CoreLibraries.gmk | 2 +- jdk/src/java.base/share/native/libzip/CRC32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index bd707071427..ea2934245df 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -225,7 +225,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \ -export:ZIP_ReadEntry -export:ZIP_GetNextEntry \ - -export:ZIP_InflateFully, \ + -export:ZIP_InflateFully -export:ZIP_CRC32, \ LIBS_unix := -ljvm -ljava $(LIBZ), \ LIBS_solaris := -lc, \ LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \ diff --git a/jdk/src/java.base/share/native/libzip/CRC32.c b/jdk/src/java.base/share/native/libzip/CRC32.c index 5d1a5c34d95..e29207b7764 100644 --- a/jdk/src/java.base/share/native/libzip/CRC32.c +++ b/jdk/src/java.base/share/native/libzip/CRC32.c @@ -54,7 +54,7 @@ Java_java_util_zip_CRC32_updateBytes0(JNIEnv *env, jclass cls, jint crc, return crc; } -JNIEXPORT jint JNICALL +jint JNICALL ZIP_CRC32(jint crc, const jbyte *buf, jint len) { return crc32(crc, (Bytef*)buf, len); From 7c15525950e393fafdb66656c1dce51100b1f316 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Wed, 24 Feb 2016 02:50:14 +0000 Subject: [PATCH 105/139] 8149417: Use final restricted flag Reviewed-by: mullan, weijun, coffeys --- .../classes/javax/crypto/JceSecurity.java | 5 +-- .../crypto/JceSecurity/FinalRestricted.java | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/crypto/JceSecurity/FinalRestricted.java diff --git a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java index fa674888824..338aa12eafc 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java +++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,8 +64,7 @@ final class JceSecurity { private static final Map verifyingProviders = new IdentityHashMap<>(); - // Set the default value. May be changed in the static initializer. - private static boolean isRestricted = true; + private static final boolean isRestricted; /* * Don't let anyone instantiate this. diff --git a/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java new file mode 100644 index 00000000000..fdfa76de068 --- /dev/null +++ b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149417 + * @summary Use final restricted flag + */ + +import java.security.*; +import java.lang.reflect.*; + +public class FinalRestricted { + + public static void main(String[] args) throws Exception { + + int modifiers = Class.forName("javax.crypto.JceSecurity") + .getDeclaredField("isRestricted").getModifiers(); + if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers) && + Modifier.isPrivate(modifiers))) { + throw new Exception("JceSecurity.isRestricted is not " + + "a private static final field!"); + } + } +} From 4ccb461831829d8e241ba9ae350da18d85e6119e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 15 Feb 2016 16:59:56 -0800 Subject: [PATCH 106/139] 8150204: (fs) Enhance java/nio/file/Files/probeContentType/Basic.java debugging output Add debugging information to the test. Reviewed-by: alanb --- .../file/Files/probeContentType/Basic.java | 80 ++++++++++++++++--- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/jdk/test/java/nio/file/Files/probeContentType/Basic.java b/jdk/test/java/nio/file/Files/probeContentType/Basic.java index 02298b48fef..ec90ed6b18c 100644 --- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java +++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,9 @@ * @run main/othervm Basic */ -import java.nio.file.*; import java.io.*; +import java.nio.file.*; +import java.util.stream.Stream; /** * Uses Files.probeContentType to probe html file, custom file type, and minimal @@ -38,6 +39,9 @@ import java.io.*; */ public class Basic { + private static final boolean IS_UNIX = + ! System.getProperty("os.name").startsWith("Windows"); + static Path createHtmlFile() throws IOException { Path file = Files.createTempFile("foo", ".html"); try (OutputStream out = Files.newOutputStream(file)) { @@ -51,10 +55,61 @@ public class Basic { return Files.createTempFile("red", ".grape"); } - static void checkContentTypes(String[] extensions, String[] expectedTypes) + private static int checkContentTypes(String expected, String actual) { + assert expected != null; + assert actual != null; + + if (!expected.equals(actual)) { + if (IS_UNIX) { + Path userMimeTypes = + Paths.get(System.getProperty("user.home"), ".mime.types"); + if (!Files.exists(userMimeTypes)) { + System.out.println(userMimeTypes + " does not exist"); + } else if (!Files.isReadable(userMimeTypes)) { + System.out.println(userMimeTypes + " is not readable"); + } else { + System.out.println(userMimeTypes + " contents:"); + try (Stream lines = Files.lines(userMimeTypes)) { + lines.forEach(System.out::println); + System.out.println(""); + } catch (IOException ioe) { + System.err.println("Problem reading " + + userMimeTypes); + } + } + + Path etcMimeTypes = Paths.get("/etc/mime.types"); + if (!Files.exists(etcMimeTypes)) { + System.out.println(etcMimeTypes + " does not exist"); + } else if (!Files.isReadable(etcMimeTypes)) { + System.out.println(etcMimeTypes + " is not readable"); + } else { + System.out.println(etcMimeTypes + " contents:"); + try (Stream lines = Files.lines(etcMimeTypes)) { + lines.forEach(System.out::println); + System.out.println(""); + } catch (IOException ioe) { + System.err.println("Problem reading " + + etcMimeTypes); + } + } + } + + System.err.println("Expected \"" + expected + + "\" but obtained \"" + + actual + "\""); + + return 1; + } + + return 0; + } + + static int checkOSXContentTypes(String[] extensions, String[] expectedTypes) throws IOException { if (extensions.length != expectedTypes.length) { - throw new IllegalArgumentException("Parameter array lengths differ"); + throw new IllegalArgumentException + ("Parameter array lengths differ"); } int failures = 0; @@ -79,12 +134,11 @@ public class Basic { } } - if (failures > 0) { - throw new RuntimeException("Test failed!"); - } + return failures; } public static void main(String[] args) throws IOException { + int failures = 0; // exercise default file type detector Path file = createHtmlFile(); @@ -93,8 +147,7 @@ public class Basic { if (type == null) { System.err.println("Content type cannot be determined - test skipped"); } else { - if (!type.equals("text/html")) - throw new RuntimeException("Unexpected type: " + type); + failures += checkContentTypes("text/html", type); } } finally { Files.delete(file); @@ -106,8 +159,7 @@ public class Basic { String type = Files.probeContentType(file); if (type == null) throw new RuntimeException("Custom file type detector not installed?"); - if (!type.equals("grape/unknown")) - throw new RuntimeException("Unexpected type: " + type); + failures += checkContentTypes("grape/unknown", type); } finally { Files.delete(file); } @@ -122,7 +174,11 @@ public class Basic { "image/jpeg", "audio/mpeg", "video/mp4", "application/pdf", "image/png" }; - checkContentTypes(extensions, expectedTypes); + failures += checkOSXContentTypes(extensions, expectedTypes); + } + + if (failures > 0) { + throw new RuntimeException("Test failed!"); } } } From f14d43a22bb8a835faa6ede4c5a10dbf3aa3f28c Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 15 Feb 2016 17:17:58 -0800 Subject: [PATCH 107/139] 6469561: javadoc for annotation types should not display "public abstract" modifiers on methods 6469562: Use compact notation to display annotation values Reviewed-by: jjg --- .../formats/html/AbstractMemberWriter.java | 9 ++++-- .../formats/html/HtmlDocletWriter.java | 13 ++++++--- .../TestAnnotationTypes.java | 21 ++++++++++++-- .../pkg/AnnotationType.java | 4 +-- .../TestRepeatedAnnotations.java | 8 +++--- .../doclet/testRepeatedAnnotations/pkg/C.java | 14 +++++----- .../doclet/testRepeatedAnnotations/pkg/D.java | 4 +-- .../TestTypeAnnotations.java | 28 +++++++++---------- .../testTypeAnnotations/typeannos/Throws.java | 4 +-- .../typeannos/Wildcards.java | 10 +++---- 10 files changed, 69 insertions(+), 46 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index c963b909a52..aa04f515ea1 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -261,10 +261,13 @@ public abstract class AbstractMemberWriter { // According to JLS, we should not be showing public modifier for // interface methods. if ((utils.isField(member) || utils.isMethod(member)) - && writer instanceof ClassWriterImpl - && utils.isInterface(((ClassWriterImpl) writer).getTypeElement())) { + && ((writer instanceof ClassWriterImpl + && utils.isInterface(((ClassWriterImpl) writer).getTypeElement()) || + writer instanceof AnnotationTypeWriterImpl) )) { // Remove the implicit abstract and public modifiers - if (utils.isMethod(member) && utils.isInterface(member.getEnclosingElement())) { + if (utils.isMethod(member) && + (utils.isInterface(member.getEnclosingElement()) || + utils.isAnnotationType(member.getEnclosingElement()))) { set.remove(ABSTRACT); set.remove(PUBLIC); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 6658c4ca531..c5daf0fa50b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -2363,7 +2363,9 @@ public class HtmlDocletWriter extends HtmlDocWriter { if (!map.isEmpty()) { annotation.addContent("("); boolean isFirst = true; - for (ExecutableElement element : map.keySet()) { + Set keys = map.keySet(); + boolean multipleValues = keys.size() > 1; + for (ExecutableElement element : keys) { if (isFirst) { isFirst = false; } else { @@ -2376,9 +2378,12 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } } - annotation.addContent(getDocLink(LinkInfoImpl.Kind.ANNOTATION, - element, element.getSimpleName().toString(), false)); - annotation.addContent("="); + String simpleName = element.getSimpleName().toString(); + if (multipleValues || !"value".equals(simpleName)) { // Omit "value=" where unnecessary + annotation.addContent(getDocLink(LinkInfoImpl.Kind.ANNOTATION, + element, simpleName, false)); + annotation.addContent("="); + } AnnotationValue annotationValue = map.get(element); List annotationTypeValues = new ArrayList<>(); new SimpleAnnotationValueVisitor9() { diff --git a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java index 657919c16e1..29f7d70e70c 100644 --- a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java +++ b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4973609 8015249 8025633 8026567 + * @bug 4973609 8015249 8025633 8026567 6469561 * @summary Make sure that annotation types with 0 members does not have * extra HR tags. * @author jamieh @@ -61,7 +61,7 @@ public class TestAnnotationTypes extends JavadocTester { + " ", "", "

      DEFAULT_NAME

      \n" - + "
      public static final java."
      +                + "
      static final java."
                       + "lang.String DEFAULT_NAME
      "); checkOutput("pkg/AnnotationType.html", true, @@ -70,6 +70,21 @@ public class TestAnnotationTypes extends JavadocTester { "
    • Detail: 
    • \n" + "
    • Field | 
    • "); + checkOutput("pkg/AnnotationType.html", true, + "", + "
        ", + "
      • ", + "", + "", + "

        Element Detail

        ", + "", + "", + "", + "
          ", + "
        • ", + "

          value

          ", + "
          int value
          " ); + checkOutput("pkg/AnnotationType.html", false, "
          \n\n" + "

          \n\n" diff --git a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/pkg/AnnotationType.java b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/pkg/AnnotationType.java index 701f651dca6..4f430af20ca 100644 --- a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/pkg/AnnotationType.java +++ b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/pkg/AnnotationType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * 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,5 +32,5 @@ import java.lang.annotation.*; * @since 1.5 */ @Documented public @interface AnnotationType { - + int value(); } diff --git a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java index fa0ff4aa02a..38380fcd5cf 100644 --- a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java +++ b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8005092 + * @bug 8005092 6469562 * @summary Test repeated annotations output. * @author bpatel * @library ../lib @@ -57,7 +57,7 @@ public class TestRepeatedAnnotations extends JavadocTester { + "title=\"annotation in pkg\">@ContaineeRegDoc", "@RegContainerDoc" - + "(value={" + + "({" + "@RegContaineeNotDoc," + "@ContaineeSynthDoc", "@ContainerSynthDoc(" - + "value=" + + "" + "@ContaineeSynthDoc)", "y={1,2})", "@NonSynthDocContainer" - + "(value=" + + "(" + "@RegArryDoc)"); checkOutput("pkg1/C.html", true, diff --git a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/C.java b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/C.java index 1c42b4fcf73..c8b628926fb 100644 --- a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/C.java +++ b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/C.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,15 +23,15 @@ package pkg; -@ContainerSynthDoc(value={@ContaineeSynthDoc,@ContaineeSynthDoc}) -@ContainerRegDoc(value={@ContaineeRegDoc,@ContaineeRegDoc}) -@RegContainerDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc}) -@ContainerRegNotDoc(value={@RegContaineeDoc,@RegContaineeDoc}) -@RegContainerNotDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc}) +@ContainerSynthDoc({@ContaineeSynthDoc,@ContaineeSynthDoc}) +@ContainerRegDoc({@ContaineeRegDoc,@ContaineeRegDoc}) +@RegContainerDoc({@RegContaineeNotDoc,@RegContaineeNotDoc}) +@ContainerRegNotDoc({@RegContaineeDoc,@RegContaineeDoc}) +@RegContainerNotDoc({@RegContaineeNotDoc,@RegContaineeNotDoc}) @ContaineeSynthDoc @ContaineeSynthDoc @ContaineeSynthDoc public class C { - @ContainerSynthDoc(value={@ContaineeSynthDoc}) + @ContainerSynthDoc({@ContaineeSynthDoc}) public void test1() {} @ContaineeSynthDoc @ContaineeSynthDoc diff --git a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/D.java b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/D.java index 35cf349e104..15592471ab2 100644 --- a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/D.java +++ b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/pkg/D.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,6 @@ public class D { @RegArryDoc(y={1,2}) public void test2() {} - @NonSynthDocContainer(value={@RegArryDoc}) + @NonSynthDocContainer({@RegArryDoc}) public void test3() {} } diff --git a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java index 2a12adfd4cd..dbbee51a9fe 100644 --- a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java +++ b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8005091 8009686 8025633 8026567 + * @bug 8005091 8009686 8025633 8026567 6469562 * @summary Make sure that type annotations are displayed correctly * @author Bhavesh Patel * @library ../lib @@ -260,13 +260,13 @@ public class TestTypeAnnotations extends JavadocTester { checkOutput("typeannos/ThrWithValue.html", true, "

          void oneException()\n"
                           + "           throws @ThrB(value=\"m\") java.lang.Exception
          ", + + "annotation in typeannos\">@ThrB(" + + "\"m\") java.lang.Exception
      ", "
      void twoExceptions()\n"
                       + "            throws @ThrB(value=\"m\") java.lang.RuntimeException,\n"
      +                + "annotation in typeannos\">@ThrB("
      +                + "\"m\") java.lang.RuntimeException,\n"
                       + "                   @ThrA java.lang.Exception
      "); @@ -293,14 +293,14 @@ public class TestTypeAnnotations extends JavadocTester { checkOutput("typeannos/BoundWithValue.html", true, "
      void wcSuper(MyList<? super @WldB(value=\"m\") java.lang."
      +                + "WldB.html\" title=\"annotation in typeannos\">@WldB("
      +                + "\"m\") java.lang."
                       + "String> l)
      ", "
      MyList<? extends @WldB(value=\"m\") java.lang.String"
      +                + "html\" title=\"annotation in typeannos\">@WldB("
      +                + "\"m\") java.lang.String"
                       + "> returnWcExtends()
      "); // Test for receiver annotations (Receivers.java). @@ -314,7 +314,7 @@ public class TestTypeAnnotations extends JavadocTester { "
      java.lang.String nonVoid(@RcvrA @RcvrB"
      -                + "(value=\"m\")"
      +                + "(\"m\")"
                       + " DefaultUnmodified this)
      ", "
      <T extends java.lang.Runnable> void accept("
      @@ -337,15 +337,15 @@ public class TestTypeAnnotations extends JavadocTester {
               checkOutput("typeannos/WithValue.html", true,
                       "
      <T extends java.lang.Runnable> void accept("
                       + "@RcvrB("
      -                + "value=\"m\") WithValue this,\n"
      +                + "typeannos\">@RcvrB("
      +                + "\"m\") WithValue this,\n"
                       + "                                           T r)\n"
                       + "                                    throws java.lang.Exception
      "); checkOutput("typeannos/WithFinal.html", true, "
      java.lang.String nonVoid(@RcvrB(value=\"m\") WithFinal"
      +                + "html\" title=\"annotation in typeannos\">@RcvrB("
      +                + "\"m\") WithFinal"
                       + " this)
      "); checkOutput("typeannos/WithBody.html", true, diff --git a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Throws.java b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Throws.java index 75a31dd3ecf..62d75aad661 100644 --- a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Throws.java +++ b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Throws.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ class ThrPublicModified { class ThrWithValue { void oneException() throws @ThrB("m") Exception {} - void twoExceptions() throws @ThrB(value="m") RuntimeException, @ThrA Exception {} + void twoExceptions() throws @ThrB("m") RuntimeException, @ThrA Exception {} } @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) diff --git a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Wildcards.java b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Wildcards.java index 593115c37f1..b4f2f15473e 100644 --- a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Wildcards.java +++ b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/typeannos/Wildcards.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,10 +39,10 @@ class BoundTest { class BoundWithValue { void wcExtends(MyList l) { } - void wcSuper(MyList l) { } + void wcSuper(MyList l) { } MyList returnWcExtends() { return null; } - MyList returnWcSuper() { return null; } + MyList returnWcSuper() { return null; } MyList> complex() { return null; } } @@ -57,10 +57,10 @@ class SelfTest { class SelfWithValue { void wcExtends(MyList<@WldB("m") ?> l) { } - void wcSuper(MyList<@WldB(value="m") ?> l) { } + void wcSuper(MyList<@WldB("m") ?> l) { } MyList<@WldB("m") ?> returnWcExtends() { return null; } - MyList<@WldB(value="m") ?> returnWcSuper() { return null; } + MyList<@WldB("m") ?> returnWcSuper() { return null; } MyList<@WldB("m") ? extends MyList<@WldB("m") ? super String>> complex() { return null; } } From 4054254344ded96254cc750a063f4159a4395457 Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Mon, 15 Feb 2016 17:47:53 -0800 Subject: [PATCH 108/139] 8132734: JDK 9 runtime changes to support multi-release jar files JEP 238 Multi-Release JAR Files runtime support Reviewed-by: alanb, psandoz, sherman --- .../classes/java/net/JarURLConnection.java | 8 + .../classes/java/util/jar/Attributes.java | 10 +- .../share/classes/java/util/jar/JarFile.java | 478 ++++++++++++++++-- .../share/classes/sun/misc/URLClassPath.java | 10 +- .../sun/net/www/protocol/jar/URLJarFile.java | 27 +- .../net/www/protocol/jar/JarFileFactory.java | 12 +- .../net/www/protocol/jar/JarFileFactory.java | 12 +- .../util/jar/JarFile/MultiReleaseJarAPI.java | 177 +++++++ .../MultiReleaseJarHttpProperties.java | 156 ++++++ .../jar/JarFile/MultiReleaseJarIterators.java | 228 +++++++++ .../JarFile/MultiReleaseJarProperties.java | 200 ++++++++ .../jar/JarFile/MultiReleaseJarSecurity.java | 108 ++++ .../jar/MultiReleaseJarURLConnection.java | 117 +++++ 13 files changed, 1483 insertions(+), 60 deletions(-) create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java create mode 100644 jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java diff --git a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java index 70dedec795e..4c7e0ab6f94 100644 --- a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java @@ -173,6 +173,14 @@ public abstract class JarURLConnection extends URLConnection { } jarFileURL = new URL(spec.substring(0, separator++)); + /* + * The url argument may have had a runtime fragment appended, so + * we need to add a runtime fragment to the jarFileURL to enable + * runtime versioning when the underlying jar file is opened. + */ + if ("runtime".equals(url.getRef())) { + jarFileURL = new URL(jarFileURL, "#runtime"); + } entryName = null; /* if ! is the last letter of the innerURL, entryName is null */ diff --git a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java index f2a01acbdba..b99755b4bb6 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -646,5 +646,13 @@ public class Attributes implements Map, Cloneable { * manifest attribute used for package versioning. */ public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor"); + + /** + * {@code Name} object for {@code Multi-Release} + * manifest attribute that indicates this is a multi-release JAR file. + * + * @since 9 + */ + public static final Name MULTI_RELEASE = new Name("Multi-Release"); } } diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 62734ceefbd..d5032fed2fd 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -28,6 +28,7 @@ package java.util.jar; import java.io.*; import java.lang.ref.SoftReference; import java.net.URL; +import java.security.PrivilegedAction; import java.util.*; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -37,28 +38,91 @@ import java.security.cert.Certificate; import java.security.AccessController; import java.security.CodeSource; import jdk.internal.misc.SharedSecrets; -import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.security.util.SignatureFileVerifier; +import static java.util.jar.Attributes.Name.MULTI_RELEASE; + /** * The {@code JarFile} class is used to read the contents of a jar file * from any file that can be opened with {@code java.io.RandomAccessFile}. * It extends the class {@code java.util.zip.ZipFile} with support - * for reading an optional {@code Manifest} entry. The - * {@code Manifest} can be used to specify meta-information about the - * jar file and its entries. + * for reading an optional {@code Manifest} entry, and support for + * processing multi-release jar files. The {@code Manifest} can be used + * to specify meta-information about the jar file and its entries. + * + *

      A multi-release jar file is a jar file that contains + * a manifest with a main attribute named "Multi-Release", + * a set of "base" entries, some of which are public classes with public + * or protected methods that comprise the public interface of the jar file, + * and a set of "versioned" entries contained in subdirectories of the + * "META-INF/versions" directory. The versioned entries are partitioned by the + * major version of the Java platform. A versioned entry, with a version + * {@code n}, {@code 8 < n}, in the "META-INF/versions/{n}" directory overrides + * the base entry as well as any entry with a version number {@code i} where + * {@code 8 < i < n}. + * + *

      By default, a {@code JarFile} for a multi-release jar file is configured + * to process the multi-release jar file as if it were a plain (unversioned) jar + * file, and as such an entry name is associated with at most one base entry. + * The {@code JarFile} may be configured to process a multi-release jar file by + * creating the {@code JarFile} with the + * {@link JarFile#JarFile(File, boolean, int, Release)} constructor. The + * {@code Release} object sets a maximum version used when searching for + * versioned entries. When so configured, an entry name + * can correspond with at most one base entry and zero or more versioned + * entries. A search is required to associate the entry name with the latest + * versioned entry whose version is less than or equal to the maximum version + * (see {@link #getEntry(String)}). + * + *

      Class loaders that utilize {@code JarFile} to load classes from the + * contents of {@code JarFile} entries should construct the {@code JarFile} + * by invoking the {@link JarFile#JarFile(File, boolean, int, Release)} + * constructor with the value {@code Release.RUNTIME} assigned to the last + * argument. This assures that classes compatible with the major + * version of the running JVM are loaded from multi-release jar files. + * + *

      If the verify flag is on when opening a signed jar file, the content of + * the file is verified against its signature embedded inside the file. Please + * note that the verification process does not include validating the signer's + * certificate. A caller should inspect the return value of + * {@link JarEntry#getCodeSigners()} to further determine if the signature + * can be trusted. * *

      Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. * - * If the verify flag is on when opening a signed jar file, the content of the - * file is verified against its signature embedded inside the file. Please note - * that the verification process does not include validating the signer's - * certificate. A caller should inspect the return value of - * {@link JarEntry#getCodeSigners()} to further determine if the signature - * can be trusted. + * @implNote + *

      + * If the API can not be used to configure a {@code JarFile} (e.g. to override + * the configuration of a compiled application or library), two {@code System} + * properties are available. + *
        + *
      • + * {@code jdk.util.jar.version} can be assigned a value that is the + * {@code String} representation of a non-negative integer + * {@code <= Version.current().major()}. The value is used to set the effective + * runtime version to something other than the default value obtained by + * evaluating {@code Version.current().major()}. The effective runtime version + * is the version that the {@link JarFile#JarFile(File, boolean, int, Release)} + * constructor uses when the value of the last argument is + * {@code Release.RUNTIME}. + *
      • + *
      • + * {@code jdk.util.jar.enableMultiRelease} can be assigned one of the three + * {@code String} values true, false, or force. The + * value true, the default value, enables multi-release jar file + * processing. The value false disables multi-release jar processing, + * ignoring the "Multi-Release" manifest attribute, and the versioned + * directories in a multi-release jar file if they exist. Furthermore, + * the method {@link JarFile#isMultiRelease()} returns false. The value + * force causes the {@code JarFile} to be initialized to runtime + * versioning after construction. It effectively does the same as this code: + * {@code (new JarFile(File, boolean, int, Release.RUNTIME)}. + *
      • + *
      + *
      * * @author David Connelly * @see Manifest @@ -68,26 +132,126 @@ import sun.security.util.SignatureFileVerifier; */ public class JarFile extends ZipFile { + private final static int BASE_VERSION; + private final static int RUNTIME_VERSION; + private final static boolean MULTI_RELEASE_ENABLED; + private final static boolean MULTI_RELEASE_FORCED; private SoftReference manRef; private JarEntry manEntry; private JarVerifier jv; private boolean jvInitialized; private boolean verify; + private final int version; + private boolean notVersioned; + private final boolean runtimeVersioned; // indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true) private boolean hasClassPathAttribute; // true if manifest checked for special attributes private volatile boolean hasCheckedSpecialAttributes; - // Set up JavaUtilJarAccess in SharedSecrets static { + // Set up JavaUtilJarAccess in SharedSecrets SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl()); + + BASE_VERSION = 8; // one less than lowest version for versioned entries + RUNTIME_VERSION = AccessController.doPrivileged( + new PrivilegedAction() { + public Integer run() { + Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated + Integer i = Integer.getInteger("jdk.util.jar.version", v); + i = i < 0 ? 0 : i; + return i > v ? v : i; + } + } + ); + String multi_release = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("jdk.util.jar.enableMultiRelease", "true"); + } + } + ); + switch (multi_release) { + case "true": + default: + MULTI_RELEASE_ENABLED = true; + MULTI_RELEASE_FORCED = false; + break; + case "false": + MULTI_RELEASE_ENABLED = false; + MULTI_RELEASE_FORCED = false; + break; + case "force": + MULTI_RELEASE_ENABLED = true; + MULTI_RELEASE_FORCED = true; + break; + } } + /** + * A set of constants that represent the entries in either the base directory + * or one of the versioned directories in a multi-release jar file. It's + * possible for a multi-release jar file to contain versioned directories + * that are not represented by the constants of the {@code Release} enum. + * In those cases, the entries will not be located by this {@code JarFile} + * through the aliasing mechanism, but they can be directly accessed by + * specifying the full path name of the entry. + * + * @since 9 + */ + public enum Release { + /** + * Represents unversioned entries, or entries in "regular", as opposed + * to multi-release jar files. + */ + BASE(BASE_VERSION), + + /** + * Represents entries found in the META-INF/versions/9 directory of a + * multi-release jar file. + */ + VERSION_9(9), + + // fill in the "blanks" for future releases + + /** + * Represents entries found in the META-INF/versions/{n} directory of a + * multi-release jar file, where {@code n} is the effective runtime + * version of the jar file. + * + * @implNote + *
      + * The effective runtime version is determined + * by evaluating {@code Version.current().major()} or by using the value + * of the {@code jdk.util.jar.version} System property if it exists. + *
      + */ + RUNTIME(RUNTIME_VERSION); + + Release(int version) { + this.version = version; + } + + private static Release valueOf(int version) { + return version <= BASE.value() ? BASE : valueOf("VERSION_" + version); + } + + private final int version; + + private int value() { + return this.version; + } + } + + private static final String META_INF = "META-INF/"; + + private static final String META_INF_VERSIONS = META_INF + "versions/"; + /** * The JAR manifest file name. */ - public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; + public static final String MANIFEST_NAME = META_INF + "MANIFEST.MF"; /** * Creates a new {@code JarFile} to read from the specified @@ -129,7 +293,6 @@ class JarFile extends ZipFile { this(file, true, ZipFile.OPEN_READ); } - /** * Creates a new {@code JarFile} to read from the specified * {@code File} object. @@ -144,7 +307,6 @@ class JarFile extends ZipFile { this(file, verify, ZipFile.OPEN_READ); } - /** * Creates a new {@code JarFile} to read from the specified * {@code File} object in the specified mode. The mode argument @@ -162,10 +324,104 @@ class JarFile extends ZipFile { * @since 1.3 */ public JarFile(File file, boolean verify, int mode) throws IOException { - super(file, mode); - this.verify = verify; + this(file, verify, mode, Release.BASE); + this.notVersioned = true; } + /** + * Creates a new {@code JarFile} to read from the specified + * {@code File} object in the specified mode. The mode argument + * must be either {@code OPEN_READ} or {@code OPEN_READ | OPEN_DELETE}. + * The version argument configures the {@code JarFile} for processing + * multi-release jar files. + * + * @param file the jar file to be opened for reading + * @param verify whether or not to verify the jar file if + * it is signed. + * @param mode the mode in which the file is to be opened + * @param version specifies the release version for a multi-release jar file + * @throws IOException if an I/O error has occurred + * @throws IllegalArgumentException + * if the {@code mode} argument is invalid + * @throws SecurityException if access to the file is denied + * by the SecurityManager + * @throws NullPointerException if {@code version} is {@code null} + * @since 9 + */ + public JarFile(File file, boolean verify, int mode, Release version) throws IOException { + super(file, mode); + Objects.requireNonNull(version); + this.verify = verify; + // version applies to multi-release jar files, ignored for regular jar files + this.version = MULTI_RELEASE_FORCED ? RUNTIME_VERSION : version.value(); + this.runtimeVersioned = version == Release.RUNTIME; + assert runtimeVersionExists(); + } + + private boolean runtimeVersionExists() { + int version = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 integrated + try { + Release.valueOf(version); + return true; + } catch (IllegalArgumentException x) { + System.err.println("No JarFile.Release object for release " + version); + return false; + } + } + + /** + * Returns the maximum version used when searching for versioned entries. + * + * @return the maximum version, or {@code Release.BASE} if this jar file is + * processed as if it is an unversioned jar file or is not a + * multi-release jar file + * @since 9 + */ + public final Release getVersion() { + if (isMultiRelease()) { + return runtimeVersioned ? Release.RUNTIME : Release.valueOf(version); + } else { + return Release.BASE; + } + } + + /** + * Indicates whether or not this jar file is a multi-release jar file. + * + * @return true if this JarFile is a multi-release jar file + * @since 9 + */ + public final boolean isMultiRelease() { + // do not call this code in a constructor because some subclasses use + // lazy loading of manifest so it won't be available at construction time + if (MULTI_RELEASE_ENABLED) { + // Doubled-checked locking pattern + Boolean result = isMultiRelease; + if (result == null) { + synchronized (this) { + result = isMultiRelease; + if (result == null) { + Manifest man = null; + try { + man = getManifest(); + } catch (IOException e) { + //Ignored, manifest cannot be read + } + isMultiRelease = result = (man != null) + && man.getMainAttributes().containsKey(MULTI_RELEASE) + ? Boolean.TRUE : Boolean.FALSE; + } + } + } + return result == Boolean.TRUE; + } else { + return false; + } + } + // the following field, isMultiRelease, should only be used in the method + // isMultiRelease(), like a static local + private volatile Boolean isMultiRelease; // is jar multi-release? + /** * Returns the jar file manifest, or {@code null} if none. * @@ -209,40 +465,87 @@ class JarFile extends ZipFile { } /** - * Returns the {@code JarEntry} for the given entry name or + * Returns the {@code JarEntry} for the given base entry name or * {@code null} if not found. * + *

      If this {@code JarFile} is a multi-release jar file and is configured + * to be processed as such, then a search is performed to find and return + * a {@code JarEntry} that is the latest versioned entry associated with the + * given entry name. The returned {@code JarEntry} is the versioned entry + * corresponding to the given base entry name prefixed with the string + * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for + * which an entry exists. If such a versioned entry does not exist, then + * the {@code JarEntry} for the base entry is returned, otherwise + * {@code null} is returned if no entries are found. The initial value for + * the version {@code n} is the maximum version as returned by the method + * {@link JarFile#getVersion()}. + * * @param name the jar file entry name - * @return the {@code JarEntry} for the given entry name or - * {@code null} if not found. + * @return the {@code JarEntry} for the given entry name, or + * the versioned entry name, or {@code null} if not found * * @throws IllegalStateException * may be thrown if the jar file has been closed * * @see java.util.jar.JarEntry + * + * @implSpec + *

      + * This implementation invokes {@link JarFile#getEntry(String)}. + *
      */ public JarEntry getJarEntry(String name) { return (JarEntry)getEntry(name); } /** - * Returns the {@code ZipEntry} for the given entry name or + * Returns the {@code ZipEntry} for the given base entry name or * {@code null} if not found. * + *

      If this {@code JarFile} is a multi-release jar file and is configured + * to be processed as such, then a search is performed to find and return + * a {@code ZipEntry} that is the latest versioned entry associated with the + * given entry name. The returned {@code ZipEntry} is the versioned entry + * corresponding to the given base entry name prefixed with the string + * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for + * which an entry exists. If such a versioned entry does not exist, then + * the {@code ZipEntry} for the base entry is returned, otherwise + * {@code null} is returned if no entries are found. The initial value for + * the version {@code n} is the maximum version as returned by the method + * {@link JarFile#getVersion()}. + * * @param name the jar file entry name * @return the {@code ZipEntry} for the given entry name or - * {@code null} if not found + * the versioned entry name or {@code null} if not found * * @throws IllegalStateException * may be thrown if the jar file has been closed * * @see java.util.zip.ZipEntry + * + * @implSpec + *

      + * This implementation may return a versioned entry for the requested name + * even if there is not a corresponding base entry. This can occur + * if there is a private or package-private versioned entry that matches. + * If a subclass overrides this method, assure that the override method + * invokes {@code super.getEntry(name)} to obtain all versioned entries. + *
      */ public ZipEntry getEntry(String name) { ZipEntry ze = super.getEntry(name); if (ze != null) { return new JarFileEntry(ze); } + // no matching base entry, but maybe there is a versioned entry, + // like a new private class + if (isMultiRelease()) { + ze = new ZipEntry(name); + ZipEntry vze = getVersionedEntry(ze); + if (ze != vze) { + return new JarFileEntry(name, vze); + } + } return null; } @@ -250,14 +553,42 @@ class JarFile extends ZipFile { Iterator { final Enumeration e = JarFile.super.entries(); + ZipEntry ze; public boolean hasNext() { - return e.hasMoreElements(); + if (notVersioned) { + return e.hasMoreElements(); + } + if (ze != null) { + return true; + } + return findNext(); + } + + private boolean findNext() { + while (e.hasMoreElements()) { + ZipEntry ze2 = e.nextElement(); + if (!ze2.getName().startsWith(META_INF_VERSIONS)) { + ze = ze2; + return true; + } + } + return false; } public JarEntry next() { - ZipEntry ze = e.nextElement(); - return new JarFileEntry(ze); + ZipEntry ze2; + + if (notVersioned) { + ze2 = e.nextElement(); + return new JarFileEntry(ze2.getName(), ze2); + } + if (ze != null || findNext()) { + ze2 = ze; + ze = null; + return new JarFileEntry(ze2); + } + throw new NoSuchElementException(); } public boolean hasMoreElements() { @@ -274,7 +605,19 @@ class JarFile extends ZipFile { } /** - * Returns an enumeration of the jar file entries. + * Returns an enumeration of the jar file entries. The set of entries + * returned depends on whether or not the jar file is a multi-release jar + * file, and on the constructor used to create the {@code JarFile}. If the + * jar file is not a multi-release jar file, all entries are returned, + * regardless of how the {@code JarFile} is created. If the constructor + * does not take a {@code Release} argument, all entries are returned. + * If the jar file is a multi-release jar file and the constructor takes a + * {@code Release} argument, then the set of entries returned is equivalent + * to the set of entries that would be returned if the set was built by + * invoking {@link JarFile#getEntry(String)} or + * {@link JarFile#getJarEntry(String)} with the name of each base entry in + * the jar file. A base entry is an entry whose path name does not start + * with "META-INF/versions/". * * @return an enumeration of the jar file entries * @throws IllegalStateException @@ -285,10 +628,21 @@ class JarFile extends ZipFile { } /** - * Returns an ordered {@code Stream} over the jar file entries. + * Returns an ordered {@code Stream} over all the jar file entries. * Entries appear in the {@code Stream} in the order they appear in - * the central directory of the jar file. - * + * the central directory of the jar file. The set of entries + * returned depends on whether or not the jar file is a multi-release jar + * file, and on the constructor used to create the {@code JarFile}. If the + * jar file is not a multi-release jar file, all entries are returned, + * regardless of how the {@code JarFile} is created. If the constructor + * does not take a {@code Release} argument, all entries are returned. + * If the jar file is a multi-release jar file and the constructor takes a + * {@code Release} argument, then the set of entries returned is equivalent + * to the set of entries that would be returned if the set was built by + * invoking {@link JarFile#getEntry(String)} or + * {@link JarFile#getJarEntry(String)} with the name of each base entry in + * the jar file. A base entry is an entry whose path name does not start + * with "META-INF/versions/". * @return an ordered {@code Stream} of entries in this jar file * @throws IllegalStateException if the jar file has been closed * @since 1.8 @@ -300,14 +654,44 @@ class JarFile extends ZipFile { Spliterator.IMMUTABLE | Spliterator.NONNULL), false); } + private ZipEntry searchForVersionedEntry(final int version, String name) { + ZipEntry vze = null; + String sname = "/" + name; + int i = version; + while (i > BASE_VERSION) { + vze = super.getEntry(META_INF_VERSIONS + i + sname); + if (vze != null) break; + i--; + } + return vze; + } + + private ZipEntry getVersionedEntry(ZipEntry ze) { + ZipEntry vze = null; + if (version > BASE_VERSION && !ze.isDirectory()) { + String name = ze.getName(); + if (!name.startsWith(META_INF)) { + vze = searchForVersionedEntry(version, name); + } + } + return vze == null ? ze : vze; + } + private class JarFileEntry extends JarEntry { + final private String name; + JarFileEntry(ZipEntry ze) { - super(ze); + super(isMultiRelease() ? getVersionedEntry(ze) : ze); + this.name = ze.getName(); + } + JarFileEntry(String name, ZipEntry vze) { + super(vze); + this.name = name; } public Attributes getAttributes() throws IOException { Manifest man = JarFile.this.getManifest(); if (man != null) { - return man.getAttributes(getName()); + return man.getAttributes(super.getName()); } else { return null; } @@ -319,7 +703,7 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (certs == null && jv != null) { - certs = jv.getCerts(JarFile.this, this); + certs = jv.getCerts(JarFile.this, reifiedEntry()); } return certs == null ? null : certs.clone(); } @@ -330,10 +714,22 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (signers == null && jv != null) { - signers = jv.getCodeSigners(JarFile.this, this); + signers = jv.getCodeSigners(JarFile.this, reifiedEntry()); } return signers == null ? null : signers.clone(); } + JarFileEntry reifiedEntry() { + if (isMultiRelease()) { + String entryName = super.getName(); + return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this); + } + return this; + } + + @Override + public String getName() { + return name; + } } /* @@ -491,12 +887,19 @@ class JarFile extends ZipFile { // wrap a verifier stream around the real stream return new JarVerifier.VerifierStream( getManifestFromReference(), - ze instanceof JarFileEntry ? - (JarEntry) ze : getJarEntry(ze.getName()), + verifiableEntry(ze), super.getInputStream(ze), jv); } + private JarEntry verifiableEntry(ZipEntry ze) { + if (!(ze instanceof JarFileEntry)) { + ze = getJarEntry(ze.getName()); + } + // assure the name and entry match for verification + return ze == null ? null : ((JarFileEntry)ze).reifiedEntry(); + } + // Statics for hand-coded Boyer-Moore search private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'}; // The bad character shift for "class-path" @@ -523,7 +926,7 @@ class JarFile extends ZipFile { private JarEntry getManEntry() { if (manEntry == null) { // First look up manifest entry using standard name - manEntry = getJarEntry(MANIFEST_NAME); + ZipEntry manEntry = super.getEntry(MANIFEST_NAME); if (manEntry == null) { // If not found, then iterate through all the "META-INF/" // entries to find a match. @@ -531,12 +934,15 @@ class JarFile extends ZipFile { if (names != null) { for (String name : names) { if (MANIFEST_NAME.equals(name.toUpperCase(Locale.ENGLISH))) { - manEntry = getJarEntry(name); + manEntry = super.getEntry(name); break; } } } } + this.manEntry = (manEntry == null) + ? null + : new JarFileEntry(manEntry.getName(), manEntry); } return manEntry; } diff --git a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java index 1ad9a2776b6..01afb44a159 100644 --- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java @@ -63,6 +63,7 @@ import java.util.jar.JarEntry; import java.util.jar.Manifest; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; +import java.util.zip.ZipFile; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; @@ -727,9 +728,10 @@ public class URLClassPath { if (!p.exists()) { throw new FileNotFoundException(p.getPath()); } - return checkJar(new JarFile(p.getPath())); + return checkJar(new JarFile(new File(p.getPath()), true, ZipFile.OPEN_READ, + JarFile.Release.RUNTIME)); } - URLConnection uc = getBaseURL().openConnection(); + URLConnection uc = (new URL(getBaseURL(), "#runtime")).openConnection(); uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION); JarFile jarFile = ((JarURLConnection)uc).getJarFile(); return checkJar(jarFile); @@ -756,7 +758,9 @@ public class URLClassPath { final URL url; try { - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + // add #runtime fragment to tell JarURLConnection to use + // runtime versioning if the underlying jar file is multi-release + url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); if (check) { URLClassPath.check(url); } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java index 1e8697ba237..fe1a1f3c8f2 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java @@ -65,9 +65,10 @@ public class URLJarFile extends JarFile { } static JarFile getJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - if (isFileURL(url)) - return new URLJarFile(url, closeController); - else { + if (isFileURL(url)) { + Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE; + return new URLJarFile(url, closeController, version); + } else { return retrieve(url, closeController); } } @@ -89,8 +90,13 @@ public class URLJarFile extends JarFile { this.closeController = closeController; } - private URLJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - super(ParseUtil.decode(url.getFile())); + private URLJarFile(File file, URLJarFileCloseController closeController, Release version) throws IOException { + super(file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE, version); + this.closeController = closeController; + } + + private URLJarFile(URL url, URLJarFileCloseController closeController, Release version) throws IOException { + super(new File(ParseUtil.decode(url.getFile())), true, ZipFile.OPEN_READ, version); this.closeController = closeController; } @@ -175,14 +181,6 @@ public class URLJarFile extends JarFile { return false; } - /** - * Given a URL, retrieves a JAR file, caches it to disk, and creates a - * cached JAR file object. - */ - private static JarFile retrieve(final URL url) throws IOException { - return retrieve(url, null); - } - /** * Given a URL, retrieves a JAR file, caches it to disk, and creates a * cached JAR file object. @@ -202,6 +200,7 @@ public class URLJarFile extends JarFile { { JarFile result = null; + Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE; /* get the stream before asserting privileges */ try (final InputStream in = url.openConnection().getInputStream()) { @@ -211,7 +210,7 @@ public class URLJarFile extends JarFile { Path tmpFile = Files.createTempFile("jar_cache", null); try { Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING); - JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController); + JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController, version); tmpFile.toFile().deleteOnExit(); return jarFile; } catch (Throwable thr) { diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java index 559fda4144f..2001c382324 100644 --- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -85,7 +85,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(URLUtil.urlNoFragString(url), local_result); + fileCache.put(urlKey(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -113,13 +113,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { URL urlRemoved = urlCache.remove(jarFile); if (urlRemoved != null) - fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + fileCache.remove(urlKey(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + JarFile result = fileCache.get(urlKey(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { @@ -149,6 +149,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return result; } + private String urlKey(URL url) { + String urlstr = URLUtil.urlNoFragString(url); + if ("runtime".equals(url.getRef())) urlstr += "#runtime"; + return urlstr; + } + private Permission getPermission(JarFile jarFile) { try { URLConnection uc = getConnection(jarFile); diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java index 07db32fc079..91bf5388460 100644 --- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -95,7 +95,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(URLUtil.urlNoFragString(url), local_result); + fileCache.put(urlKey(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -123,13 +123,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { URL urlRemoved = urlCache.remove(jarFile); if (urlRemoved != null) - fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + fileCache.remove(urlKey(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + JarFile result = fileCache.get(urlKey(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { @@ -159,6 +159,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return result; } + private String urlKey(URL url) { + String urlstr = URLUtil.urlNoFragString(url); + if ("runtime".equals(url.getRef())) urlstr += "#runtime"; + return urlstr; + } + private Permission getPermission(JarFile jarFile) { try { URLConnection uc = getConnection(jarFile); diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java new file mode 100644 index 00000000000..7f7653e9eab --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the extended API and the aliasing additions in JarFile that + * support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarAPI + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static java.util.jar.JarFile.Release; +import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + + +public class MultiReleaseJarAPI { + String userdir = System.getProperty("user.dir","."); + File unversioned = new File(userdir, "unversioned.jar"); + File multirelease = new File(userdir, "multi-release.jar"); + File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + Release[] values = JarFile.Release.values(); + + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildUnversionedJar(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(unversioned.toPath()); + Files.delete(multirelease.toPath()); + Files.delete(signedmultirelease.toPath()); + } + + @Test + public void isMultiReleaseJar() throws Exception { + try (JarFile jf = new JarFile(unversioned)) { + Assert.assertFalse(jf.isMultiRelease()); + } + + try (JarFile jf = new JarFile(multirelease)) { + Assert.assertTrue(jf.isMultiRelease()); + } + } + + @Test + public void testVersioning() throws Exception { + // multi-release jar + JarFile jar = new JarFile(multirelease); + Assert.assertEquals(Release.BASE, jar.getVersion()); + jar.close(); + + for (Release value : values) { + System.err.println("test versioning for Release " + value); + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) { + Assert.assertEquals(value, jf.getVersion()); + } + } + + // regular, unversioned, jar + for (Release value : values) { + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) { + Assert.assertEquals(Release.BASE, jf.getVersion()); + } + } + + // assure that we have a Release object corresponding to the actual runtime version + String version = "VERSION_" + jdkMajorVersion(); + boolean runtimeVersionExists = false; + for (Release value : values) { + if (version.equals(value.name())) runtimeVersionExists = true; + } + Assert.assertTrue(runtimeVersionExists); + } + + @Test + public void testAliasing() throws Exception { + for (Release value : values) { + System.err.println("test aliasing for Release " + value); + String name = value.name(); + String prefix; + if (name.equals("BASE")) { + prefix = ""; + } else if (name.equals("RUNTIME")) { + prefix = "META-INF/versions/" + jdkMajorVersion() + "/"; + } else { + prefix = "META-INF/versions/" + name.substring(8) + "/"; + } + // test both multi-release jars + readAndCompare(multirelease, value, "README", prefix + "README"); + readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class"); + // and signed multi-release jars + readAndCompare(signedmultirelease, value, "README", prefix + "README"); + readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class"); + } + } + + private void readAndCompare(File jar, Release version, String name, String realName) throws Exception { + byte[] baseBytes; + byte[] versionedBytes; + try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) { + ZipEntry ze = jf.getEntry(realName); + try (InputStream is = jf.getInputStream(ze)) { + baseBytes = is.readAllBytes(); + } + } + assert baseBytes.length > 0; + + try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) { + ZipEntry ze = jf.getEntry(name); + try (InputStream is = jf.getInputStream(ze)) { + versionedBytes = is.readAllBytes(); + } + } + assert versionedBytes.length > 0; + + Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes)); + } + + @Test + public void testNames() throws Exception { + String rname = "version/Version.class"; + String vname = "META-INF/versions/9/version/Version.class"; + ZipEntry ze1; + ZipEntry ze2; + try (JarFile jf = new JarFile(multirelease)) { + ze1 = jf.getEntry(vname); + } + Assert.assertEquals(ze1.getName(), vname); + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + ze2 = jf.getEntry(rname); + } + Assert.assertEquals(ze2.getName(), rname); + Assert.assertNotEquals(ze1.getName(), ze2.getName()); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java new file mode 100644 index 00000000000..f80991d09d5 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the System properties for JarFile that support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + */ + +import com.sun.net.httpserver.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { + private SimpleHttpServer server; + + @BeforeClass + public void initialize() throws Exception { + server = new SimpleHttpServer(); + server.start(); + super.initialize(); + } + + @Override + protected void initializeClassLoader() throws Exception { + URL[] urls = new URL[]{ + new URL("http://localhost:" + server.getPort() + "/multi-release-jar") + }; + cldr = new URLClassLoader(urls); + // load any class, Main is convenient and in the root entries + rootClass = cldr.loadClass("version.Main"); + } + + @AfterClass + public void close() throws IOException { + // Windows requires server to stop before file is deleted + if (server != null) + server.stop(); + super.close(); + } + + /* + * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader + */ + + @Test + public void testURLClassLoader() throws Throwable { + Class vcls = cldr.loadClass("version.Version"); + invokeMethod(vcls, rtVersion); + } + + @Test + public void testGetResourceAsStream() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResourceAsStream(rootClass, resource); + } + + @Test + public void testGetResource() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResource(rootClass, resource); + } +} + +/** + * Extremely simple server that only performs one task. The server listens for + * requests on the ephemeral port. If it sees a request that begins with + * "/multi-release-jar", it consumes the request and returns a stream of bytes + * representing the jar file multi-release.jar found in "userdir". + */ +class SimpleHttpServer { + private static final String userdir = System.getProperty("user.dir", "."); + private static final Path multirelease = Paths.get(userdir, "multi-release.jar"); + + private final HttpServer server; + + public SimpleHttpServer() throws IOException { + server = HttpServer.create(); + } + + public void start() throws IOException { + server.bind(new InetSocketAddress(0), 0); + server.createContext("/multi-release-jar", t -> { + try (InputStream is = t.getRequestBody()) { + is.readAllBytes(); // probably not necessary to consume request + byte[] bytes = Files.readAllBytes(multirelease); + t.sendResponseHeaders(200, bytes.length); + try (OutputStream os = t.getResponseBody()) { + os.write(bytes); + } + } + }); + server.setExecutor(null); // creates a default executor + server.start(); + } + + public void stop() { + server.stop(0); + } + + int getPort() { + return server.getAddress().getPort(); + } +} + diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java new file mode 100644 index 00000000000..587bf6e5da1 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the extended API and the aliasing additions in JarFile that + * support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarIterators + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.zip.ZipFile; + +import static java.util.jar.JarFile.Release; +import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + + +public class MultiReleaseJarIterators { + String userdir = System.getProperty("user.dir", "."); + File unversioned = new File(userdir, "unversioned.jar"); + File multirelease = new File(userdir, "multi-release.jar"); + Map uvEntries = new HashMap<>(); + Map mrEntries = new HashMap<>(); + Map baseEntries = new HashMap<>(); + Map v9Entries = new HashMap<>(); + Map v10Entries = new HashMap<>(); + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildUnversionedJar(); + creator.buildMultiReleaseJar(); + + try (JarFile jf = new JarFile(multirelease)) { + for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { + JarEntry je = e.nextElement(); + String name = je.getName(); + mrEntries.put(name, je); + if (name.startsWith("META-INF/versions/")) { + if (name.startsWith("META-INF/versions/9/")) { + v9Entries.put(name.substring(20), je); + } else if (name.startsWith("META-INF/versions/10/")) { + v10Entries.put(name.substring(21), je); + } + } else { + baseEntries.put(name, je); + } + } + } + Assert.assertEquals(mrEntries.size(), 14); + Assert.assertEquals(baseEntries.size(), 6); + Assert.assertEquals(v9Entries.size(), 5); + Assert.assertEquals(v10Entries.size(), 3); + + try (JarFile jf = new JarFile(unversioned)) { + jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je)); + } + Assert.assertEquals(uvEntries.size(), 6); + } + + @AfterClass + public void close() throws IOException { + Files.delete(unversioned.toPath()); + Files.delete(multirelease.toPath()); + } + + @Test + public void testMultiReleaseJar() throws IOException { + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) { + testEnumeration(jf, mrEntries); + testStream(jf, mrEntries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) { + testEnumeration(jf, baseEntries); + testStream(jf, baseEntries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + testEnumeration(jf, v9Entries); + testStream(jf, v9Entries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) { + Map expectedEntries; + switch (jdkMajorVersion()) { + case 9: + expectedEntries = v9Entries; + break; + case 10: // won't get here until JDK 10 + expectedEntries = v10Entries; + break; + default: + expectedEntries = baseEntries; + break; + } + + testEnumeration(jf, expectedEntries); + testStream(jf, expectedEntries); + } + } + + @Test + public void testUnversionedJar() throws IOException { + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + } + + private void testEnumeration(JarFile jf, Map expectedEntries) { + Map actualEntries = new HashMap<>(); + for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { + JarEntry je = e.nextElement(); + actualEntries.put(je.getName(), je); + } + + testEntries(jf, actualEntries, expectedEntries); + } + + + private void testStream(JarFile jf, Map expectedEntries) { + Map actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je)); + + testEntries(jf, actualEntries, expectedEntries); + } + + private void testEntries(JarFile jf, Map actualEntries, Map expectedEntries) { + /* For multi-release jar files constructed with a Release object, + * actualEntries contain versionedEntries that are considered part of the + * public API. They have a 1-1 correspondence with baseEntries, + * so entries that are not part of the public API won't be present, + * i.e. those entries with a name that starts with version/PackagePrivate + * in this particular jar file (multi-release.jar) + */ + + Map entries; + if (expectedEntries == mrEntries) { + Assert.assertEquals(actualEntries.size(), mrEntries.size()); + entries = mrEntries; + } else if (expectedEntries == uvEntries) { + Assert.assertEquals(actualEntries.size(), uvEntries.size()); + entries = uvEntries; + } else { + Assert.assertEquals(actualEntries.size(), baseEntries.size()); // this is correct + entries = baseEntries; + } + + entries.keySet().forEach(name -> { + JarEntry ee = expectedEntries.get(name); + if (ee == null) ee = entries.get(name); + JarEntry ae = actualEntries.get(name); + try { + compare(jf, ae, ee); + } catch (IOException x) { + throw new RuntimeException(x); + } + }); + } + + private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException { + byte[] abytes; + byte[] ebytes; + + try (InputStream is = jf.getInputStream(actual)) { + abytes = is.readAllBytes(); + } + + try (InputStream is = jf.getInputStream(expected)) { + ebytes = is.readAllBytes(); + } + + Assert.assertEquals(abytes, ebytes); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java new file mode 100644 index 00000000000..978ba328be6 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the System properties for JarFile that support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarProperties { + final static int ROOTVERSION = 8; // magic number from knowledge of internals + final static String userdir = System.getProperty("user.dir", "."); + final static File multirelease = new File(userdir, "multi-release.jar"); + protected int rtVersion; + boolean force; + protected ClassLoader cldr; + protected Class rootClass; + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + + rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion()); + String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", ""); + if (mrprop.equals("false")) { + rtVersion = ROOTVERSION; + } else if (rtVersion < ROOTVERSION) { + rtVersion = ROOTVERSION; + } else if (rtVersion > jdkMajorVersion()) { + rtVersion = jdkMajorVersion(); + } + force = mrprop.equals("force"); + + initializeClassLoader(); + } + + protected void initializeClassLoader() throws Exception { + URL[] urls = new URL[]{multirelease.toURI().toURL()}; + cldr = new URLClassLoader(urls); + // load any class, Main is convenient and in the root entries + rootClass = cldr.loadClass("version.Main"); + } + + @AfterClass + public void close() throws IOException { + ((URLClassLoader)cldr).close(); + Files.delete(multirelease.toPath()); + } + + /* + * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader + */ + @Test + public void testURLClassLoader() throws Throwable { + Class vcls = cldr.loadClass("version.Version"); + invokeMethod(vcls, rtVersion); + } + + protected void invokeMethod(Class vcls, int expected) throws Throwable { + MethodType mt = MethodType.methodType(int.class); + MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt); + Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance())); + } + + /* + * jdk.util.jar.enableMultiRelease=force should affect a custom class loader + */ + @Test + public void testClassLoader() throws Throwable { + try (JarFile jf = new JarFile(multirelease)) { // do not set runtime versioning + ClassLoader cldr = new CustomClassLoader(jf); + Class vcls = cldr.loadClass("version.Version"); + if (rtVersion == 9) { + try { + cldr.loadClass("version.PackagePrivate"); + } catch (ClassNotFoundException x) { + if (force) throw x; + } + } + invokeMethod(vcls, force ? rtVersion : ROOTVERSION); + } + } + + private static class CustomClassLoader extends ClassLoader { + private final JarFile jf; + + CustomClassLoader(JarFile jf) throws Exception { + super(null); + this.jf = jf; + } + + protected Class findClass(String name) throws ClassNotFoundException { + try { + byte[] b; + String entryName = name.replace(".", "/") + ".class"; + JarEntry je = jf.getJarEntry(entryName); + if (je != null) { + try (InputStream is = jf.getInputStream(je)) { + b = new byte[(int) je.getSize()]; + is.read(b); + } + return defineClass(name, b, 0, b.length); + } + throw new ClassNotFoundException(name); + } catch (IOException x) { + throw new ClassNotFoundException(x.getMessage()); + } + } + } + + @Test + public void testGetResourceAsStream() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use fileRootClass as a base for getting resources + getResourceAsStream(rootClass, resource); + } + + protected void getResourceAsStream(Class rootClass, String resource) throws Exception { + try (InputStream is = rootClass.getResourceAsStream(resource)) { + byte[] bytes = is.readAllBytes(); + resource = new String(bytes); + } + String match = "return " + rtVersion + ";"; + Assert.assertTrue(resource.contains(match)); + } + + @Test + public void testGetResource() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResource(rootClass, resource); + } + + protected void getResource(Class rootClass, String resource) throws Exception { + URL url = rootClass.getResource(resource); + try (InputStream is = url.openStream()) { + byte[] bytes = is.readAllBytes(); + resource = new String(bytes); + } + String match = "return " + rtVersion + ";"; + Assert.assertTrue(resource.contains(match)); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java new file mode 100644 index 00000000000..6547c990b2a --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test potential security related issues + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarSecurity + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.security.CodeSigner; +import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarSecurity { + String userdir = System.getProperty("user.dir","."); + File multirelease = new File(userdir, "multi-release.jar"); + File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(multirelease.toPath()); + Files.delete(signedmultirelease.toPath()); + } + + @Test + public void testCertsAndSigners() throws IOException { + try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) { + int version = sun.misc.Version.jdkMajorVersion(); // fixme JEP 223 Version + CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class")); + CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class")); + Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates())); + Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners())); + } + } + + private static class CertsAndSigners { + final private JarFile jf; + final private JarEntry je; + private boolean readComplete; + + CertsAndSigners(JarFile jf, JarEntry je) { + this.jf = jf; + this.je = je; + } + + Certificate[] getCertificates() throws IOException { + readEntry(); + return je.getCertificates(); + } + + CodeSigner[] getCodeSigners() throws IOException { + readEntry(); + return je.getCodeSigners(); + } + + private void readEntry() throws IOException { + if (!readComplete) { + try (InputStream is = jf.getInputStream(je)) { + is.readAllBytes(); + } + readComplete = true; + } + } + } +} diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java new file mode 100644 index 00000000000..a500eb2e25c --- /dev/null +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test that URL connections to multi-release jars can be runtime versioned + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarURLConnection + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.jar.JarFile; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarURLConnection { + String userdir = System.getProperty("user.dir","."); + String urlFile = "jar:file:" + userdir + "/multi-release.jar!/"; + String urlEntry = urlFile + "version/Version.java"; + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(Paths.get(userdir, "multi-release.jar")); + } + + @Test + public void testRuntimeVersioning() throws Exception { + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + // #runtime is "magic" + Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9")); + // #fragment or any other fragment is not magic + Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8")); + // cached entities not affected + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + } + + @Test + public void testCachedJars() throws Exception { + URL rootUrl = new URL(urlFile); + JarURLConnection juc = (JarURLConnection)rootUrl.openConnection(); + JarFile rootJar = juc.getJarFile(); + JarFile.Release root = rootJar.getVersion(); + + URL runtimeUrl = new URL(urlFile + "#runtime"); + juc = (JarURLConnection)runtimeUrl.openConnection(); + JarFile runtimeJar = juc.getJarFile(); + JarFile.Release runtime = runtimeJar.getVersion(); + Assert.assertNotEquals(root, runtime); + + juc = (JarURLConnection)rootUrl.openConnection(); + JarFile jar = juc.getJarFile(); + Assert.assertEquals(jar.getVersion(), root); + Assert.assertEquals(jar, rootJar); + + juc = (JarURLConnection)runtimeUrl.openConnection(); + jar = juc.getJarFile(); + Assert.assertEquals(jar.getVersion(), runtime); + Assert.assertEquals(jar, runtimeJar); + + rootJar.close(); + runtimeJar.close(); + jar.close(); // probably not needed + } + + private boolean readAndCompare(URL url, String match) throws Exception { + boolean result; + // necessary to do it this way, instead of openStream(), so we can + // close underlying JarFile, otherwise windows can't delete the file + URLConnection conn = url.openConnection(); + try (InputStream is = conn.getInputStream()) { + byte[] bytes = is.readAllBytes(); + result = (new String(bytes)).contains(match); + } + if (conn instanceof JarURLConnection) { + ((JarURLConnection)conn).getJarFile().close(); + } + return result; + } +} From bd2fa9abe6fe8ed85be4b0eefc39cc7a35ca9313 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 15 Feb 2016 19:52:03 -0800 Subject: [PATCH 109/139] 8149886: 16 windows tests broke with recent putback Reviewed-by: sundar --- .../com/sun/tools/doclets/internal/toolkit/util/Extern.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java index e043db17293..350e80707e1 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,8 +257,8 @@ public class Extern { try { if (file.exists() && file.canRead()) { boolean pathIsRelative = - !DocFile.createFileForInput(configuration, path).isAbsolute() - && !isUrl(path); + !isUrl(path) + && !DocFile.createFileForInput(configuration, path).isAbsolute(); readPackageList(file.openInputStream(), path, pathIsRelative); } else { throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null); From 68fd352eb8644a66258071d9db1c92eb26a53a2a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 15 Feb 2016 22:21:39 -0800 Subject: [PATCH 110/139] 8149903: Fix other Extern Reviewed-by: darcy --- .../jdk/javadoc/internal/doclets/toolkit/util/Extern.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java index e9b66c0478f..eebcc5e6686 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java @@ -261,8 +261,8 @@ public class Extern { try { if (file.exists() && file.canRead()) { boolean pathIsRelative = - !DocFile.createFileForInput(configuration, path).isAbsolute() - && !isUrl(path); + !isUrl(path) + && !DocFile.createFileForInput(configuration, path).isAbsolute(); readPackageList(file.openInputStream(), path, pathIsRelative); } else { throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null); From b33be1774dd91dc44bcc90bb7e5e06eacedc3ed2 Mon Sep 17 00:00:00 2001 From: Mark Sheppard Date: Tue, 16 Feb 2016 12:37:44 +0000 Subject: [PATCH 111/139] 8144144: ORB destroy() leaks filedescriptors after unsuccessful connection Reviewed-by: chegar, coffeys --- .../CorbaInboundConnectionCacheImpl.java | 20 +++++ .../transport/CorbaTransportManagerImpl.java | 5 +- .../corba/se/impl/transport/SelectorImpl.java | 90 ++++++++++++++++--- .../SocketOrChannelAcceptorImpl.java | 30 +++++-- .../SocketOrChannelConnectionImpl.java | 13 ++- .../transport/InboundConnectionCache.java | 2 + 6 files changed, 135 insertions(+), 25 deletions(-) diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaInboundConnectionCacheImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaInboundConnectionCacheImpl.java index 220c7874311..1f2f855781a 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaInboundConnectionCacheImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaInboundConnectionCacheImpl.java @@ -54,11 +54,17 @@ public class CorbaInboundConnectionCacheImpl { protected Collection connectionCache; + private Acceptor acceptor; + public CorbaInboundConnectionCacheImpl(ORB orb, Acceptor acceptor) { super(orb, acceptor.getConnectionCacheType(), ((CorbaAcceptor)acceptor).getMonitoringName()); this.connectionCache = new ArrayList(); + this.acceptor = acceptor; + if (orb.transportDebugFlag) { + dprint(": " + acceptor ); + } } //////////////////////////////////////////////////// @@ -66,11 +72,25 @@ public class CorbaInboundConnectionCacheImpl // pept.transport.InboundConnectionCache // + public void close () { + + super.close(); + if (orb.transportDebugFlag) { + dprint(".close: " + acceptor ); + } + this.acceptor.close(); + + } + public Connection get(Acceptor acceptor) { throw wrapper.methodShouldNotBeCalled(); } + public Acceptor getAcceptor () { + return acceptor; + } + public void put(Acceptor acceptor, Connection connection) { if (orb.transportDebugFlag) { diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java index 12c0be64e2f..970fde4a873 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java @@ -188,8 +188,9 @@ public class CorbaTransportManagerImpl for (Object cc : outboundConnectionCaches.values()) { ((ConnectionCache)cc).close() ; } - for (Object cc : inboundConnectionCaches.values()) { - ((ConnectionCache)cc).close() ; + for (Object icc : inboundConnectionCaches.values()) { + ((ConnectionCache)icc).close() ; + unregisterAcceptor(((InboundConnectionCache)icc).getAcceptor()); } getSelector(0).close(); } finally { diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java index c43c1dfa7b5..016fd945abf 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java @@ -26,16 +26,20 @@ package com.sun.corba.se.impl.transport; import java.io.IOException; +import java.net.ServerSocket; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; +import java.nio.channels.ServerSocketChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; +import java.nio.channels.ClosedSelectorException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Iterator; import java.util.List; + import com.sun.corba.se.pept.broker.Broker; import com.sun.corba.se.pept.transport.Acceptor; import com.sun.corba.se.pept.transport.Connection; @@ -111,7 +115,16 @@ class SelectorImpl interestOpsList.add(keyAndOp); } // tell Selector Thread there's an update to a SelectorKey's Ops - selector.wakeup(); + try { + if (selector != null) { + // wakeup Selector thread to process close request + selector.wakeup(); + } + } catch (Throwable t) { + if (orb.transportDebugFlag) { + dprint(".registerInterestOps: selector.wakeup: ", t); + } + } } else { wrapper.selectionKeyInvalid(eventHandler.toString()); @@ -186,7 +199,9 @@ class SelectorImpl if (selectionKey != null) { selectionKey.cancel(); } - selector.wakeup(); + if (selector != null) { + selector.wakeup(); + } return; } @@ -239,6 +254,8 @@ class SelectorImpl readerThread.close(); } + clearDeferredRegistrations(); + // Selector try { @@ -248,7 +265,7 @@ class SelectorImpl } } catch (Throwable t) { if (orb.transportDebugFlag) { - dprint(".close: selector.close: " + t); + dprint(".close: selector.wakeup: ", t); } } } @@ -273,15 +290,16 @@ class SelectorImpl n = selector.select(timeout); } catch (IOException e) { if (orb.transportDebugFlag) { - dprint(".run: selector.select: " + e); + dprint(".run: selector.select: ", e); } + } catch (ClosedSelectorException csEx) { + if (orb.transportDebugFlag) { + dprint(".run: selector.select: ", csEx); + } + break; } if (closed) { - selector.close(); - if (orb.transportDebugFlag) { - dprint(".run: closed - .run return"); - } - return; + break; } /* if (timeout == 0 && orb.transportDebugFlag) { @@ -321,6 +339,18 @@ class SelectorImpl } } } + try { + if (selector != null) { + if (orb.transportDebugFlag) { + dprint(".run: selector.close "); + } + selector.close(); + } + } catch (Throwable t) { + if (orb.transportDebugFlag) { + dprint(".run: selector.close: ", t); + } + } } ///////////////////////////////////////////////////// @@ -328,6 +358,44 @@ class SelectorImpl // Implementation. // + private void clearDeferredRegistrations() { + synchronized (deferredRegistrations) { + int deferredListSize = deferredRegistrations.size(); + if (orb.transportDebugFlag) { + dprint(".clearDeferredRegistrations:deferred list size == " + deferredListSize); + } + for (int i = 0; i < deferredListSize; i++) { + EventHandler eventHandler = + (EventHandler)deferredRegistrations.get(i); + if (orb.transportDebugFlag) { + dprint(".clearDeferredRegistrations: " + eventHandler); + } + SelectableChannel channel = eventHandler.getChannel(); + SelectionKey selectionKey = null; + + try { + if (orb.transportDebugFlag) { + dprint(".clearDeferredRegistrations:close channel == " + + channel); + dprint(".clearDeferredRegistrations:close channel class == " + + channel.getClass().getName()); + } + channel.close(); + selectionKey = eventHandler.getSelectionKey(); + if (selectionKey != null) { + selectionKey.cancel(); + selectionKey.attach(null); + } + } catch (IOException ioEx) { + if (orb.transportDebugFlag) { + dprint(".clearDeferredRegistrations: ", ioEx); + } + } + } + deferredRegistrations.clear(); + } + } + private synchronized boolean isClosed () { return closed; @@ -344,7 +412,7 @@ class SelectorImpl selector = Selector.open(); } catch (IOException e) { if (orb.transportDebugFlag) { - dprint(".startSelector: Selector.open: IOException: " + e); + dprint(".startSelector: Selector.open: IOException: ", e); } // REVISIT - better handling/reporting RuntimeException rte = @@ -379,7 +447,7 @@ class SelectorImpl (Object)eventHandler); } catch (ClosedChannelException e) { if (orb.transportDebugFlag) { - dprint(".handleDeferredRegistrations: " + e); + dprint(".handleDeferredRegistrations: ", e); } } eventHandler.setSelectionKey(selectionKey); diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java index 18023b5b9de..4b24c6b8376 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelAcceptorImpl.java @@ -264,7 +264,12 @@ public class SocketOrChannelAcceptorImpl if (connection.shouldRegisterServerReadEvent()) { Selector selector = orb.getTransportManager().getSelector(0); - selector.registerForEvent(connection.getEventHandler()); + if (selector != null) { + if (orb.transportDebugFlag) { + dprint(".accept: registerForEvent: " + connection); + } + selector.registerForEvent(connection.getEventHandler()); + } } getConnectionCache().reclaim(); @@ -273,12 +278,15 @@ public class SocketOrChannelAcceptorImpl if (orb.transportDebugFlag) { dprint(".accept:", e); } - orb.getTransportManager().getSelector(0).unregisterForEvent(this); - // REVISIT - need to close - recreate - then register new one. - orb.getTransportManager().getSelector(0).registerForEvent(this); - // NOTE: if register cycling we do not want to shut down ORB - // since local beans will still work. Instead one will see - // a growing log file to alert admin of problem. + Selector selector = orb.getTransportManager().getSelector(0); + if (selector != null) { + selector.unregisterForEvent(this); + // REVISIT - need to close - recreate - then register new one. + selector.registerForEvent(this); + // NOTE: if register cycling we do not want to shut down ORB + // since local beans will still work. Instead one will see + // a growing log file to alert admin of problem. + } } } @@ -289,7 +297,9 @@ public class SocketOrChannelAcceptorImpl dprint(".close->:"); } Selector selector = orb.getTransportManager().getSelector(0); - selector.unregisterForEvent(this); + if (selector != null) { + selector.unregisterForEvent(this); + } if (serverSocketChannel != null) { serverSocketChannel.close(); } @@ -480,7 +490,9 @@ public class SocketOrChannelAcceptorImpl // of calling SelectionKey.interestOps(). Selector selector = orb.getTransportManager().getSelector(0); - selector.registerInterestOps(this); + if (selector != null) { + selector.registerInterestOps(this); + } if (orb.transportDebugFlag) { dprint(".doWork<-:" + this); diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java index fa87b568df4..f7c1e314eec 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java @@ -367,7 +367,10 @@ public class SocketOrChannelConnectionImpl } } // REVISIT - make sure reader thread is killed. - orb.getTransportManager().getSelector(0).unregisterForEvent(this); + Selector selector = orb.getTransportManager().getSelector(0); + if (selector != null) { + selector.unregisterForEvent(this); + } // Notify anyone waiting. purgeCalls(wrapper.connectionAbort(ex), true, false); // REVISIT @@ -801,7 +804,9 @@ public class SocketOrChannelConnectionImpl } try { Selector selector = orb.getTransportManager().getSelector(0); - selector.unregisterForEvent(this); + if (selector != null) { + selector.unregisterForEvent(this); + } if (socketChannel != null) { socketChannel.close(); } @@ -824,7 +829,9 @@ public class SocketOrChannelConnectionImpl dprint(".closeConnectionResources->: " + this); } Selector selector = orb.getTransportManager().getSelector(0); - selector.unregisterForEvent(this); + if (selector != null) { + selector.unregisterForEvent(this); + } try { if (socketChannel != null) socketChannel.close() ; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/pept/transport/InboundConnectionCache.java b/corba/src/java.corba/share/classes/com/sun/corba/se/pept/transport/InboundConnectionCache.java index a79e1ff04e9..3aee07176d7 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/pept/transport/InboundConnectionCache.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/pept/transport/InboundConnectionCache.java @@ -36,6 +36,8 @@ public interface InboundConnectionCache public void put(Acceptor acceptor, Connection connection); public void remove(Connection connection); + + public Acceptor getAcceptor(); } // End of file. From 18677d77f69a66b2df54baf4e8dff8bca90fbad5 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Tue, 16 Feb 2016 15:34:27 +0100 Subject: [PATCH 112/139] 8148140: arguments are handled differently in apply for JS functions and AbstractJSObjects Reviewed-by: hannesw, sundar --- .../runtime/linker/JSObjectLinker.java | 10 ++- .../api/scripting/test/JDK_8148140_Test.java | 73 +++++++++++++++++++ .../runtime/test/JDK_8142924_Test.java | 24 ++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java index 4f05e78922b..9c8cce036ed 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.JSType.isString; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.Map; import javax.script.Bindings; import jdk.dynalink.CallSiteDescriptor; @@ -135,12 +136,15 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { } private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) { - // TODO: if call site is already a vararg, don't do asCollector MethodHandle mh = JSOBJECT_CALL; if (NashornCallSiteDescriptor.isApplyToCall(desc)) { mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL); } - return new GuardedInvocation(MH.asCollector(mh, Object[].class, desc.getMethodType().parameterCount() - 2), IS_JSOBJECT_GUARD); + final MethodType type = desc.getMethodType(); + mh = type.parameterType(type.parameterCount() - 1) == Object[].class ? + mh : + MH.asCollector(mh, Object[].class, type.parameterCount() - 2); + return new GuardedInvocation(mh, IS_JSOBJECT_GUARD); } private static GuardedInvocation findNewMethod(final CallSiteDescriptor desc) { diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java new file mode 100644 index 00000000000..fcf3df7251b --- /dev/null +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.nashorn.internal.runtime.test; + +import java.util.Arrays; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import jdk.nashorn.api.scripting.AbstractJSObject; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/** + * @bug 8148140 + * @summary arguments are handled differently in apply for JS functions and AbstractJSObjects + */ +public class JDK_8148140_Test { + + ScriptEngine engine; + + static final String RESULT = "[1, 2, 3]"; + + @BeforeClass + public void setupTest() { + engine = new ScriptEngineManager().getEngineByName("js"); + engine.put("f", new AbstractJSObject() { + @Override + public boolean isFunction() { + return true; + } + @Override + public Object call(Object thiz, Object... args) { + return Arrays.deepToString(args); + } + }); + } + + @Test + public void testCallF() throws ScriptException { + assertEquals(RESULT, engine.eval("f(1,2,3)")); + } + + @Test + public void testApplyF() throws ScriptException { + assertEquals(RESULT, engine.eval("Function.prototype.apply.call(f, null, [1,2,3])")); + } + +} \ No newline at end of file diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8142924_Test.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8142924_Test.java index 5f3fc160ea4..68b24935918 100644 --- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8142924_Test.java +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8142924_Test.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ package jdk.nashorn.internal.runtime.test; import java.io.ByteArrayInputStream; From f2cf4159bc263fb436205a364aa3da566f79e2b3 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 17 Feb 2016 17:03:08 +0100 Subject: [PATCH 113/139] 8149963: build errors during API docs build Reviewed-by: ihse, tbell --- make/Javadoc.gmk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk index 05093f4612a..0e0be3fc47e 100644 --- a/make/Javadoc.gmk +++ b/make/Javadoc.gmk @@ -212,6 +212,11 @@ JDK_API_DOCSDIR = $(DOCSDIR)/jdk/api JRE_API_DOCSDIR = $(DOCSDIR)/jre/api PLATFORM_DOCSDIR = $(DOCSDIR)/platform +# The core api index file is the target for the core api javadocs rule +# and needs to be defined early so that all other javadoc rules may +# depend on it. +COREAPI_INDEX_FILE = $(COREAPI_DOCSDIR)/index.html + # The non-core api javadocs need to be able to access the root of the core # api directory, so for jdk/api or jre/api to get to the core api/ # directory we would use this: @@ -363,8 +368,7 @@ COREAPI_HEADER = \ # Overview file for core apis COREAPI_OVERVIEW = $(JDK_TOPDIR)/src/java.base/share/classes/overview-core.html -# The index.html, options, and packages files -COREAPI_INDEX_FILE = $(COREAPI_DOCSDIR)/index.html +# The options and packages files COREAPI_OPTIONS_FILE = $(DOCSTMPDIR)/coredocs.options COREAPI_PACKAGES_FILE = $(DOCSTMPDIR)/coredocs.packages From 512b3becc640d3171920aaf8324a36e5cb93425e Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 17 Feb 2016 19:29:25 +0300 Subject: [PATCH 114/139] 8149835: StringConcatFactory should emit classes with the same package as the host class Reviewed-by: psandoz, alanb, mchung --- langtools/test/tools/javac/TestIndyStringConcat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/TestIndyStringConcat.java b/langtools/test/tools/javac/TestIndyStringConcat.java index 713cd53c867..b799f70015b 100644 --- a/langtools/test/tools/javac/TestIndyStringConcat.java +++ b/langtools/test/tools/javac/TestIndyStringConcat.java @@ -60,7 +60,7 @@ public class TestIndyStringConcat { boolean indifiedStringConcat = false; ex.printStackTrace(); for (StackTraceElement e : ex.getStackTrace()) { - if (e.getClassName().startsWith("java.lang.String$Concat") && + if (e.getClassName().contains("$$StringConcat") && e.getMethodName().equals("concat")) { indifiedStringConcat = true; break; From 33dcb43fe9ab8fb230617def4933a2aecf178ad8 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 17 Feb 2016 11:19:07 -0800 Subject: [PATCH 115/139] 8149842: javadoc incorrectly tries to get the documentation for inherited methods Reviewed-by: jjg --- .../jdk/javadoc/internal/tool/DocEnv.java | 15 ++--- .../doclet/testIncluded/TestIncluded.java | 55 +++++++++++++++++++ .../javadoc/doclet/testIncluded/parent/A.java | 30 ++++++++++ .../javadoc/doclet/testIncluded/pkg/B.java | 35 ++++++++++++ 4 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java create mode 100644 langtools/test/jdk/javadoc/doclet/testIncluded/parent/A.java create mode 100644 langtools/test/jdk/javadoc/doclet/testIncluded/pkg/B.java diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java index 1168986a93b..0be30ebf45a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java @@ -705,14 +705,6 @@ public class DocEnv { return false; } - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Boolean defaultAction(Element e, Void p) { - if (includedSet.contains(e) || shouldDocument(e)) { - return true; - } - return false; - } - @Override @DefinedBy(Api.LANGUAGE_MODEL) public Boolean visitPackage(PackageElement e, Void p) { return includedSet.contains(e); @@ -720,7 +712,12 @@ public class DocEnv { @Override @DefinedBy(Api.LANGUAGE_MODEL) public Boolean visitUnknown(Element e, Void p) { - throw new AssertionError("got element: " + e); + throw new AssertionError("unknown element: " + e); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Boolean defaultAction(Element e, Void p) { + return visit(e.getEnclosingElement()) && shouldDocument(e); } }; } diff --git a/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java new file mode 100644 index 00000000000..2abe9f05a29 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149468 + * @summary Verify that non included classes are not inspected. + * @library ../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build JavadocTester + * @run main TestIncluded + */ + +public class TestIncluded extends JavadocTester { + + public static void main(String... args) throws Exception { + TestIncluded tester = new TestIncluded(); + tester.runTests(); + } + + /* + * The arguments specify only "pkg" but "parent" sources are on the path. + * The class parent.A utilizes a non existent taglet, that will trigger + * an error, if doc comments are inspected. + */ + @Test + void test() { + javadoc("-d", "out", + "-Xdoclint:all", + "-sourcepath", testSrc, + "pkg"); + checkExit(Exit.OK); + checkFiles(false, "parent/A.html"); + } +} diff --git a/langtools/test/jdk/javadoc/doclet/testIncluded/parent/A.java b/langtools/test/jdk/javadoc/doclet/testIncluded/parent/A.java new file mode 100644 index 00000000000..9a990eb3063 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testIncluded/parent/A.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 parent; +public class A { + /** + * Does nothing. Uses an non existent taglet {@enoexist no errors please}. + */ + public void method(){} +} diff --git a/langtools/test/jdk/javadoc/doclet/testIncluded/pkg/B.java b/langtools/test/jdk/javadoc/doclet/testIncluded/pkg/B.java new file mode 100644 index 00000000000..dc9fbc46cf7 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testIncluded/pkg/B.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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; + +/** + * Just a lonesome class. + */ +public class B extends parent.A { + /** + * The main method. + * @param args the aaaaargs + */ + public static void main(String... args) {} +} From 97deaa28b9720b16c400c4b50d95f4668d450d47 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 17 Feb 2016 19:09:44 +0100 Subject: [PATCH 116/139] 8150077: Due to a javac type inference issue, javadoc doesn't compile with a jdk prior to 8u40 Reviewed-by: jjg --- .../jdk/javadoc/internal/doclets/toolkit/util/Utils.java | 2 +- .../share/classes/jdk/javadoc/internal/tool/RootDocImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index eb9d0240732..5914a2e6013 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -176,7 +176,7 @@ public class Utils { List excludeList = members.stream() .filter((member) -> (!isDeprecated(member))) .sorted(makeGeneralPurposeComparator()) - .collect(Collectors.toCollection(ArrayList::new)); + .collect(Collectors.>toCollection(ArrayList::new)); return excludeList; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/RootDocImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/RootDocImpl.java index 2e6d63cf000..1f122c9e43b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/RootDocImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/RootDocImpl.java @@ -272,7 +272,7 @@ public class RootDocImpl implements DocletEnvironment { public List getSelectedElements(List elements) { return elements.stream() .filter(e -> isIncluded(e)) - .collect(Collectors.toList()); + .collect(Collectors.toList()); } @Override From ffa5558ae1571bd8ea3cde2455a2118bbbca69be Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Wed, 17 Feb 2016 16:32:51 -0800 Subject: [PATCH 117/139] 8146237: PREFER from Features API taking precedence over catalog file Reviewed-by: lancea --- .../javax/xml/catalog/CatalogReader.java | 5 +++- .../jaxp/unittest/catalog/CatalogTest.java | 25 ++++++++++++++++++- .../unittest/catalog/JDK8146237_catalog.xml | 7 ++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 jaxp/test/javax/xml/jaxp/unittest/catalog/JDK8146237_catalog.xml diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java index f41caf1f7e0..0235bff1311 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,11 +184,14 @@ class CatalogReader extends DefaultHandler implements EntityResolver, URIResolve if (resolve == null) { resolve = catalog.getResolve().literal; } + //override property settings with those from the catalog file catalog.setResolve(resolve); + catalog.setPrefer(defer); catalogEntry = new CatalogEntry(base, prefer, defer, resolve); } else { catalogEntry = new CatalogEntry(base, prefer); } + catalog.setPrefer(prefer); return; } else { inGroup = true; diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java index 08830042132..706df66fceb 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java @@ -23,6 +23,7 @@ package catalog; import java.io.IOException; +import javax.xml.catalog.Catalog; import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogFeatures.Feature; import javax.xml.catalog.CatalogManager; @@ -41,15 +42,36 @@ import org.xml.sax.XMLReader; import org.xml.sax.ext.DefaultHandler2; /* - * @bug 8081248, 8144966, 8146606 + * @bug 8081248, 8144966, 8146606, 8146237 * @summary Tests basic Catalog functions. */ public class CatalogTest { + /** + * @bug 8146237 + * PREFER from Features API taking precedence over catalog file + */ + @Test + public void testJDK8146237() { + String catalogFile = getClass().getResource("JDK8146237_catalog.xml").getFile(); + + try { + CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, "system").build(); + Catalog catalog = CatalogManager.catalog(features, catalogFile); + CatalogResolver catalogResolver = CatalogManager.catalogResolver(catalog); + String actualSystemId = catalogResolver.resolveEntity("-//FOO//DTD XML Dummy V0.0//EN", "http://www.oracle.com/alt1sys.dtd").getSystemId(); + Assert.assertTrue(actualSystemId.contains("dummy.dtd"), "Resulting id should contain dummy.dtd, indicating a match by publicId"); + + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + /* @bug 8146606 Verifies that the resulting systemId does not contain duplicate slashes */ + @Test public void testRewriteSystem() { String catalog = getClass().getResource("rewriteCatalog.xml").getFile(); @@ -67,6 +89,7 @@ public class CatalogTest { @bug 8146606 Verifies that the resulting systemId does not contain duplicate slashes */ + @Test public void testRewriteUri() { String catalog = getClass().getResource("rewriteCatalog.xml").getFile(); diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/JDK8146237_catalog.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/JDK8146237_catalog.xml new file mode 100644 index 00000000000..bce1b666ac0 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/JDK8146237_catalog.xml @@ -0,0 +1,7 @@ + + + + + + From 7de236320f7f82692598fa80d2ef03547cb5913a Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 17 Feb 2016 17:45:36 -0800 Subject: [PATCH 118/139] 8074069: Move com.oracle.net and com.oracle.nio APIs to jdk.net module Reviewed-by: alanb --- modules.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules.xml b/modules.xml index e0da33a70fc..458859b5327 100644 --- a/modules.xml +++ b/modules.xml @@ -239,6 +239,7 @@ java.xml jdk.charsets jdk.management.resource + jdk.net jdk.scripting.nashorn jdk.vm.ci @@ -319,6 +320,10 @@ java.security.jgss jdk.naming.dns + + sun.net.sdp + jdk.net + sun.net.spi.nameservice jdk.naming.dns @@ -345,6 +350,7 @@ jdk.crypto.pkcs11 jdk.crypto.ucrypto jdk.management.resource + jdk.net jdk.sctp From 737538ea0390bad8ef5841426277fe5575749b7c Mon Sep 17 00:00:00 2001 From: Miroslav Kos Date: Thu, 18 Feb 2016 10:20:56 +0100 Subject: [PATCH 119/139] 8149923: invalid javadoc in javax.xml.bind.JAXBContext (introduced by 8138699) Reviewed-by: lancea --- .../share/classes/javax/xml/bind/JAXBContext.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java index adfb479a849..a2d9bceb37f 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java @@ -450,8 +450,14 @@ public abstract class JAXBContext { * in an empty map. * * @return a new instance of a {@code JAXBContext} - * @throws JAXBException if an error was encountered while creating the - * {@code JAXBContext}. See {@link #newInstance(String, ClassLoader)} for details. + * @throws JAXBException + * if an error was encountered while creating the {@code JAXBContext} such as + *
        + *
      1. failure to locate either ObjectFactory.class or jaxb.index in the packages
      2. + *
      3. an ambiguity among global elements contained in the contextPath
      4. + *
      5. failure to locate a value for the context factory provider property
      6. + *
      7. mixing schema derived packages from different providers on the same contextPath
      8. + *
      * @since 1.6, JAXB 2.0 */ public static JAXBContext newInstance( String contextPath, From b5e7cfe1ea24521423c3bf318517a308284dd599 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:08 -0800 Subject: [PATCH 120/139] Added tag jdk-9+106 for changeset c4b6c7386de8 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index fa35aec5858..aaae670d176 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -348,3 +348,4 @@ c4d72a1620835b5d657b7b6792c2879367d0154f jdk-9+101 47d6462e514b2097663305a57d9c844c15d5b609 jdk-9+103 9a38f8b4ba220708db198d08d82fd2144a64777d jdk-9+104 be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105 +54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106 From 6db2bbb17722095144fb15f5815eafdb0507851d Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:09 -0800 Subject: [PATCH 121/139] Added tag jdk-9+106 for changeset 90d9c81fe530 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 472ba0e173f..88b455ba6fb 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -348,3 +348,4 @@ ea285530245cf4e0edf0479121a41347d3030eba jdk-9+98 0680fb7dae4da1ee6cf783c4b74184e3e08d3179 jdk-9+103 e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104 64006ae915b3aa85ac7e6fac679024d2da7fe526 jdk-9+105 +8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106 From e16feff964bfd2a1d84e84fb31aa5d6d8eb8d98a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:10 -0800 Subject: [PATCH 122/139] Added tag jdk-9+106 for changeset e15ec0a78e45 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 4e4e70dca68..30bbd8fe337 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -508,3 +508,4 @@ d5239fc1b69749ae50793c61b899fcdacf3df857 jdk-9+102 c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103 534c50395957c6025fb6627e93b35756f8d48a08 jdk-9+104 266fa9bb5297bf02cb2a7b038b10a109817d2b48 jdk-9+105 +7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106 From eea26d7c7527e366f1e65fdb8674c0d6f9b7cefa Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:13 -0800 Subject: [PATCH 123/139] Added tag jdk-9+106 for changeset 6041f8d71ed1 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 552a46464cf..a985e31fc94 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -348,3 +348,4 @@ d3e834ff74e724a2b92a558e18e8cbf81c6dbc59 jdk-9+101 bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 58448465334e1d8bf1cfc09052783937b1cc21c0 jdk-9+104 5acf6071d4d610068a19c79e004ba8e59cf1b087 jdk-9+105 +65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106 From a3ba108ba51ec24692e608220cd93c0a77bfef4c Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:15 -0800 Subject: [PATCH 124/139] Added tag jdk-9+106 for changeset a42bde2f777c --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 9a3952fe0ab..f7f802b6f6b 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -351,3 +351,4 @@ d0a97e57d2336238edf6a4cd60aafe67deb7258d jdk-9+100 eb5e005a17e50d7d8340daaf21a5c3c5ae358d68 jdk-9+103 0f557aa096e2a5c9733d406d8cf0c2e6b1f8ca60 jdk-9+104 45a666c58e4c7d07638878684ad09decb3229dc9 jdk-9+105 +c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106 From 77296b1d4cde5729b364ec0e17696c1d06881ef9 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:21 -0800 Subject: [PATCH 125/139] Added tag jdk-9+106 for changeset 6a6ca0bd3c14 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 6315a8003a6..c6a2d3a75cd 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -348,3 +348,4 @@ cb73b474703e2de266542b505cffd658bcc052da jdk-9+99 94cfc50c1b8a74fd7b0ed2e9e4f4a9dab4f2c6a1 jdk-9+103 3f60a4808377a276f6398ff19e61c1b9086f4d97 jdk-9+104 81bd82222f8a1f2b291a44a49e063973caa4e73b jdk-9+105 +dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106 From 482543cb166946541062068059a7d1deaf4949aa Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 18 Feb 2016 11:30:22 -0800 Subject: [PATCH 126/139] Added tag jdk-9+106 for changeset 148bb1cd62e5 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 14581c52c21..a2b4cd909db 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -339,3 +339,4 @@ e5620875888583d35e9492b62fe27e054df26049 jdk-9+102 c9406f325a23e9093fa667ad3c594e2efe078f47 jdk-9+103 a618d3e89fdea5361895ef142a59074fe7ae3d98 jdk-9+104 4e9749cc32f15251d9b2d0eab4373529952902a3 jdk-9+105 +cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 From 50b82e8d5e3f18a99a479bf508d367cfc9e5aa66 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 18 Feb 2016 14:45:13 -0500 Subject: [PATCH 127/139] 8149750: Decouple sun.misc.Signal from the base module Reviewed-by: dholmes, chegar --- hotspot/src/share/vm/classfile/vmSymbols.hpp | 4 ++-- hotspot/src/share/vm/runtime/os.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 8188ead0ecc..626009f4c2f 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -109,13 +109,13 @@ template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \ template(java_io_Serializable, "java/io/Serializable") \ template(java_util_Arrays, "java/util/Arrays") \ - template(java_util_Objects, "java/util/Objects") \ + template(java_util_Objects, "java/util/Objects") \ template(java_util_Properties, "java/util/Properties") \ template(java_util_Vector, "java/util/Vector") \ template(java_util_AbstractList, "java/util/AbstractList") \ template(java_util_Hashtable, "java/util/Hashtable") \ template(java_lang_Compiler, "java/lang/Compiler") \ - template(sun_misc_Signal, "sun/misc/Signal") \ + template(jdk_internal_misc_Signal, "jdk/internal/misc/Signal") \ template(sun_misc_Launcher, "sun/misc/Launcher") \ template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 5aedae5bf57..c482d2135dd 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -273,7 +273,7 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) { default: { // Dispatch the signal to java HandleMark hm(THREAD); - Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_misc_Signal(), THREAD); + Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_misc_Signal(), THREAD); KlassHandle klass (THREAD, k); if (klass.not_null()) { JavaValue result(T_VOID); From 7521e9ec772f93708e3970f958b6f71113cf6fc0 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Thu, 18 Feb 2016 12:48:11 -0800 Subject: [PATCH 128/139] 8150096: Cleanup synthetic JCCompilationUnit for html files Reviewed-by: jjg --- .../com/sun/tools/doclint/Checker.java | 10 ++- .../com/sun/tools/javac/api/JavacTrees.java | 64 ++++++++++++++++++- .../internal/tool/JavadocClassFinder.java | 10 ++- .../testPackageHtml/TestPackageHtml.java | 48 ++++++++++++++ .../doclet/testPackageHtml/pkg1/X.java | 29 +++++++++ .../doclet/testPackageHtml/pkg1/package.html | 9 +++ .../doclet/testWarnings/TestWarnings.java | 9 +-- 7 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 langtools/test/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java create mode 100644 langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/X.java create mode 100644 langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/package.html diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java index 03a62b2019d..3727ddcd9e9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,13 +149,13 @@ public class Checker extends DocTreePathScanner { env.setCurrent(p, tree); boolean isOverridingMethod = !env.currOverriddenMethods.isEmpty(); + JavaFileObject fo = p.getCompilationUnit().getSourceFile(); if (p.getLeaf().getKind() == Tree.Kind.PACKAGE) { // If p points to a package, the implied declaration is the // package declaration (if any) for the compilation unit. // Handle this case specially, because doc comments are only // expected in package-info files. - JavaFileObject fo = p.getCompilationUnit().getSourceFile(); boolean isPkgInfo = fo.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); if (tree == null) { if (isPkgInfo) @@ -165,6 +165,12 @@ public class Checker extends DocTreePathScanner { if (!isPkgInfo) reportReference("dc.unexpected.comment"); } + } else if (tree != null && fo.isNameCompatible("package", JavaFileObject.Kind.HTML)) { + // a package.html file with a DocCommentTree + if (tree.getFullBody().isEmpty()) { + reportMissing("dc.missing.comment"); + return null; + } } else { if (tree == null) { if (!isSynthetic() && !isOverridingMethod) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index ef037dc28b6..d75f6f2073d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -28,7 +28,9 @@ package com.sun.tools.javac.api; import java.io.FileNotFoundException; import java.io.IOException; import java.text.BreakIterator; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -68,12 +70,16 @@ import com.sun.source.util.DocTrees; import com.sun.source.util.JavacTask; import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Scope.NamedImportScope; +import com.sun.tools.javac.code.Scope.StarImportScope; +import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.ClassType; @@ -103,6 +109,7 @@ import com.sun.tools.javac.tree.DCTree.DCIdentifier; import com.sun.tools.javac.tree.DCTree.DCParam; import com.sun.tools.javac.tree.DCTree.DCReference; import com.sun.tools.javac.tree.DCTree.DCText; +import com.sun.tools.javac.tree.DocCommentTable; import com.sun.tools.javac.tree.DocTreeMaker; import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; @@ -163,6 +170,8 @@ public class JavacTrees extends DocTrees { private BreakIterator breakIterator; private JavaFileManager fileManager; private ParserFactory parser; + private Symtab syms; + private Map javaFileObjectToPackageMap; // called reflectively from Trees.instance(CompilationTask task) public static JavacTrees instance(JavaCompiler.CompilationTask task) { @@ -186,6 +195,7 @@ public class JavacTrees extends DocTrees { } protected JavacTrees(Context context) { + javaFileObjectToPackageMap = new HashMap<>(); this.breakIterator = null; context.put(JavacTrees.class, this); init(context); @@ -207,6 +217,7 @@ public class JavacTrees extends DocTrees { types = Types.instance(context); docTreeMaker = DocTreeMaker.instance(context); parser = ParserFactory.instance(context); + syms = Symtab.instance(context); fileManager = context.get(JavaFileManager.class); JavacTask t = context.get(JavacTask.class); if (t instanceof JavacTaskImpl) @@ -1018,7 +1029,8 @@ public class JavacTrees extends DocTrees { @Override @DefinedBy(Api.COMPILER_TREE) public DocTreePath getDocTreePath(FileObject fileObject) { JavaFileObject jfo = asJavaFileObject(fileObject); - return new DocTreePath(makeTreePath(jfo), getDocCommentTree(jfo)); + DocCommentTree docCommentTree = getDocCommentTree(jfo); + return new DocTreePath(makeTreePath(jfo, docCommentTree), docCommentTree); } @Override @DefinedBy(Api.COMPILER_TREE) @@ -1136,7 +1148,17 @@ public class JavacTrees extends DocTrees { } } - private TreePath makeTreePath(final JavaFileObject jfo) { + /** + * Register a file object, such as for a package.html, that provides + * doc comments for a package. + * @param psym the PackageSymbol representing the package. + * @param jfo the JavaFileObject for the given package. + */ + public void putJavaFileObject(PackageSymbol psym, JavaFileObject jfo) { + javaFileObjectToPackageMap.putIfAbsent(jfo, psym); + } + + private TreePath makeTreePath(final JavaFileObject jfo, DocCommentTree dcTree) { JCCompilationUnit jcCompilationUnit = new JCCompilationUnit(List.nil()) { public int getPos() { return Position.FIRSTPOS; @@ -1156,8 +1178,44 @@ public class JavacTrees extends DocTrees { return null; } }; + + PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo, syms.unnamedPackage); + + jcCompilationUnit.docComments = new DocCommentTable() { + @Override + public boolean hasComment(JCTree tree) { + return false; + } + + @Override + public Comment getComment(JCTree tree) { + throw new UnsupportedOperationException(); + } + + @Override + public String getCommentText(JCTree tree) { + throw new UnsupportedOperationException(); + } + + @Override + public DCDocComment getCommentTree(JCTree tree) { + return (DCDocComment)dcTree; + } + + @Override + public void putComment(JCTree tree, Comment c) { + throw new UnsupportedOperationException(); + } + + }; + jcCompilationUnit.lineMap = jcCompilationUnit.getLineMap(); + jcCompilationUnit.namedImportScope = new NamedImportScope(psym, jcCompilationUnit.toplevelScope); + jcCompilationUnit.packge = psym; + jcCompilationUnit.starImportScope = null; jcCompilationUnit.sourcefile = jfo; - enter.main(List.of(jcCompilationUnit)); + jcCompilationUnit.starImportScope = new StarImportScope(psym); + jcCompilationUnit.toplevelScope = WriteableScope.create(psym); + return new TreePath(jcCompilationUnit); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java index f1e6b6ba6d0..d546d4ad3d3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.util.EnumSet; import javax.tools.JavaFileObject; +import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.ClassFinder; import com.sun.tools.javac.util.Context; @@ -66,10 +67,13 @@ public class JavadocClassFinder extends ClassFinder { private EnumSet noSource = EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.HTML); + private final JavacTrees trees; + public JavadocClassFinder(Context context) { super(context); docenv = DocEnv.instance(context); preferSource = true; + trees = JavacTrees.instance(context); } /** @@ -85,7 +89,9 @@ public class JavadocClassFinder extends ClassFinder { */ @Override protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) { - if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML)) + if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML)) { docenv.pkgToJavaFOMap.put(pack, fo); + trees.putJavaFileObject(pack, fo); + } } } diff --git a/langtools/test/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java b/langtools/test/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java new file mode 100644 index 00000000000..78726f0c752 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8150096 + * @summary Make sure package.html is recognized by doclint + * @library ../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build JavadocTester + * @run main TestPackageHtml + */ + +public class TestPackageHtml extends JavadocTester { + public static void main(String... args) throws Exception { + TestPackageHtml tester = new TestPackageHtml(); + tester.runTests(); + } + + @Test + void testPackageHtml() { + javadoc("-d", "out-pkg-html", + "-sourcepath", testSrc, + "pkg1"); + checkExit(Exit.FAILED); + checkOutput(Output.OUT, true, "package.html:10: error: bad use of '>'"); + } +} diff --git a/langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/X.java b/langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/X.java new file mode 100644 index 00000000000..29d1a796db5 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/X.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 pkg1; + +/** + * An empty class. + */ +public class X {} diff --git a/langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/package.html b/langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/package.html new file mode 100644 index 00000000000..a05dc5ea338 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testPackageHtml/pkg1/package.html @@ -0,0 +1,9 @@ + + + +
      +            <opaque value="TRUE"/>
      +        
      + + + diff --git a/langtools/test/jdk/javadoc/doclet/testWarnings/TestWarnings.java b/langtools/test/jdk/javadoc/doclet/testWarnings/TestWarnings.java index e3fbe7003a8..17ac8cc4bae 100644 --- a/langtools/test/jdk/javadoc/doclet/testWarnings/TestWarnings.java +++ b/langtools/test/jdk/javadoc/doclet/testWarnings/TestWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * Make sure error message starts with "error -". * @author jamieh * @library ../lib - * @modules jdk.javadoc + * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build JavadocTester * @run main TestWarnings */ @@ -61,11 +61,6 @@ public class TestWarnings extends JavadocTester { checkOutput(Output.OUT, true, "X.java:26: error: self-closing element not allowed"); - /* DCErroneous - checkOutput(Output.OUT, true, - "package.html: error - Body tag missing from HTML"); - */ - checkOutput("pkg/X.html", false, "can't find m()"); checkOutput("pkg/X.html", false, From 0b312f1dc2a4b11fc8cc1cec92a27930cc358ab0 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Thu, 18 Feb 2016 22:34:40 -0800 Subject: [PATCH 129/139] 8149451: Fix bytecode generation issue after 8149186 Reviewed-by: mhaupt, sundar --- .../internal/codegen/types/BooleanType.java | 11 +----- .../internal/codegen/types/IntType.java | 20 ++++++---- .../internal/codegen/types/LongType.java | 11 +----- .../nashorn/internal/codegen/types/Type.java | 13 +------ .../internal/runtime/linker/Bootstrap.java | 39 +------------------ 5 files changed, 19 insertions(+), 75 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/BooleanType.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/BooleanType.java index 9cc239a8436..1dcd8e8a5c5 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/BooleanType.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/BooleanType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package jdk.nashorn.internal.codegen.types; import static jdk.internal.org.objectweb.asm.Opcodes.I2D; import static jdk.internal.org.objectweb.asm.Opcodes.I2L; -import static jdk.internal.org.objectweb.asm.Opcodes.IADD; import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0; import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1; import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD; @@ -35,7 +34,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN; import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT; -import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; @@ -134,11 +132,6 @@ public final class BooleanType extends Type { @Override public Type add(final MethodVisitor method, final int programPoint) { // Adding booleans in JavaScript is perfectly valid, they add as if false=0 and true=1 - if(programPoint == INVALID_PROGRAM_POINT) { - method.visitInsn(IADD); - } else { - method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint); - } - return INT; + return Type.INT.add(method, programPoint); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java index 76c86046c01..ffad71e4e5f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -155,7 +155,8 @@ class IntType extends BitwiseType { if(programPoint == INVALID_PROGRAM_POINT) { method.visitInsn(IADD); } else { - method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint); + ldc(method, programPoint); + JSType.ADD_EXACT.invoke(method); } return INT; } @@ -214,7 +215,8 @@ class IntType extends BitwiseType { if(programPoint == INVALID_PROGRAM_POINT) { method.visitInsn(ISUB); } else { - method.visitInvokeDynamicInsn("isub", "(II)I", MATHBOOTSTRAP, programPoint); + ldc(method, programPoint); + JSType.SUB_EXACT.invoke(method); } return INT; } @@ -224,7 +226,8 @@ class IntType extends BitwiseType { if(programPoint == INVALID_PROGRAM_POINT) { method.visitInsn(IMUL); } else { - method.visitInvokeDynamicInsn("imul", "(II)I", MATHBOOTSTRAP, programPoint); + ldc(method, programPoint); + JSType.MUL_EXACT.invoke(method); } return INT; } @@ -234,7 +237,8 @@ class IntType extends BitwiseType { if (programPoint == INVALID_PROGRAM_POINT) { JSType.DIV_ZERO.invoke(method); } else { - method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint); + ldc(method, programPoint); + JSType.DIV_EXACT.invoke(method); } return INT; } @@ -244,7 +248,8 @@ class IntType extends BitwiseType { if (programPoint == INVALID_PROGRAM_POINT) { JSType.REM_ZERO.invoke(method); } else { - method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint); + ldc(method, programPoint); + JSType.REM_EXACT.invoke(method); } return INT; } @@ -254,7 +259,8 @@ class IntType extends BitwiseType { if(programPoint == INVALID_PROGRAM_POINT) { method.visitInsn(INEG); } else { - method.visitInvokeDynamicInsn("ineg", "(I)I", MATHBOOTSTRAP, programPoint); + ldc(method, programPoint); + JSType.NEGATE_EXACT.invoke(method); } return INT; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/LongType.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/LongType.java index aa4b5398a09..7a19d3bbec6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/LongType.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/LongType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ package jdk.nashorn.internal.codegen.types; import static jdk.internal.org.objectweb.asm.Opcodes.L2D; import static jdk.internal.org.objectweb.asm.Opcodes.L2I; -import static jdk.internal.org.objectweb.asm.Opcodes.LADD; import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0; import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1; import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD; @@ -35,7 +34,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN; import static jdk.internal.org.objectweb.asm.Opcodes.LSTORE; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG; -import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; @@ -125,12 +123,7 @@ class LongType extends Type { @Override public Type add(final MethodVisitor method, final int programPoint) { - if(programPoint == INVALID_PROGRAM_POINT) { - method.visitInsn(LADD); - } else { - method.visitInvokeDynamicInsn("ladd", "(JJ)J", MATHBOOTSTRAP, programPoint); - } - return LONG; + throw new UnsupportedOperationException("add"); } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java index 5b23c1cb8df..fe8ab811f2f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 +33,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.DUP2_X1; import static jdk.internal.org.objectweb.asm.Opcodes.DUP2_X2; import static jdk.internal.org.objectweb.asm.Opcodes.DUP_X1; import static jdk.internal.org.objectweb.asm.Opcodes.DUP_X2; -import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD; import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE; import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; @@ -46,28 +45,22 @@ import static jdk.internal.org.objectweb.asm.Opcodes.SWAP; import static jdk.internal.org.objectweb.asm.Opcodes.T_DOUBLE; import static jdk.internal.org.objectweb.asm.Opcodes.T_INT; import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG; -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.Serializable; -import java.lang.invoke.CallSite; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; import java.util.Collections; import java.util.Map; import java.util.TreeMap; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import jdk.internal.org.objectweb.asm.Handle; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Undefined; -import jdk.nashorn.internal.runtime.linker.Bootstrap; /** * This is the representation of a JavaScript type, disassociated from java @@ -124,10 +117,6 @@ public abstract class Type implements Comparable, BytecodeOps, Serializabl /** Set way below Integer.MAX_VALUE to prevent overflow when adding weights. Objects are still heaviest. */ protected static final int MAX_WEIGHT = 20; - static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "mathBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class); - - static final Handle MATHBOOTSTRAP = new Handle(H_INVOKESTATIC, BOOTSTRAP.className(), "mathBootstrap", BOOTSTRAP.descriptor()); - /** * Constructor * diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java index 2c3801a5fef..387ec8c96e1 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import java.lang.invoke.CallSite; -import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; @@ -203,42 +202,6 @@ public final class Bootstrap { return Context.getDynamicLinker(lookup.lookupClass()).link(LinkerCallSite.newLinkerCallSite(lookup, opDesc, type, flags)); } - /** - * Boostrapper for math calls that may overflow - * @param lookup lookup - * @param name name of operation - * @param type method type - * @param programPoint program point to bind to callsite - * - * @return callsite for a math intrinsic node - */ - public static CallSite mathBootstrap(final Lookup lookup, final String name, final MethodType type, final int programPoint) { - final MethodHandle mh; - switch (name) { - case "iadd": - mh = JSType.ADD_EXACT.methodHandle(); - break; - case "isub": - mh = JSType.SUB_EXACT.methodHandle(); - break; - case "imul": - mh = JSType.MUL_EXACT.methodHandle(); - break; - case "idiv": - mh = JSType.DIV_EXACT.methodHandle(); - break; - case "irem": - mh = JSType.REM_EXACT.methodHandle(); - break; - case "ineg": - mh = JSType.NEGATE_EXACT.methodHandle(); - break; - default: - throw new AssertionError("unsupported math intrinsic"); - } - return new ConstantCallSite(MH.insertArguments(mh, mh.type().parameterCount() - 1, programPoint)); - } - /** * Returns a dynamic invoker for a specified dynamic operation using the * public lookup. You can use this method to create a method handle that From 540c76f5b1d8da9dd3f771466322fc3a71fe4f9d Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Fri, 19 Feb 2016 09:55:37 -0800 Subject: [PATCH 130/139] 8148346: Reduce number of packages in jdk.localedata module Reviewed-by: okutsu, alanb --- jdk/make/gendata/GendataBreakIterator.gmk | 12 +-- .../tools/cldrconverter/CLDRConverter.java | 16 +++- .../ResourceBundleGenerator.java | 28 +++---- .../BreakIteratorRBControl.java | 71 ------------------ .../GenerateBreakIteratorData.java | 17 ++--- .../resources/{en => }/FormatData_en.java | 2 +- .../{en/US => }/FormatData_en_US.java | 2 +- .../{en => }/JavaTimeSupplementary_en.java | 2 +- .../{en => }/CalendarData_en.properties | 0 .../US => }/CurrencyNames_en_US.properties | 0 .../sun/util/resources/LocaleData.java | 14 ++-- .../{en => }/LocaleNames_en.properties | 0 .../resources/{en => }/TimeZoneNames_en.java | 2 +- .../{th => ext}/BreakIteratorInfo_th.java | 10 +-- .../{th => ext}/BreakIteratorRules_th.java | 2 +- .../{ar => ext}/CollationData_ar.java | 2 +- .../{be => ext}/CollationData_be.java | 2 +- .../{bg => ext}/CollationData_bg.java | 2 +- .../{ca => ext}/CollationData_ca.java | 2 +- .../{cs => ext}/CollationData_cs.java | 2 +- .../{da => ext}/CollationData_da.java | 2 +- .../{el => ext}/CollationData_el.java | 2 +- .../{es => ext}/CollationData_es.java | 2 +- .../{et => ext}/CollationData_et.java | 2 +- .../{fi => ext}/CollationData_fi.java | 2 +- .../{fr => ext}/CollationData_fr.java | 2 +- .../{hi => ext}/CollationData_hi.java | 2 +- .../{hr => ext}/CollationData_hr.java | 2 +- .../{hu => ext}/CollationData_hu.java | 2 +- .../{is => ext}/CollationData_is.java | 2 +- .../{iw => ext}/CollationData_iw.java | 2 +- .../{ja => ext}/CollationData_ja.java | 2 +- .../{ko => ext}/CollationData_ko.java | 2 +- .../{lt => ext}/CollationData_lt.java | 2 +- .../{lv => ext}/CollationData_lv.java | 2 +- .../{mk => ext}/CollationData_mk.java | 2 +- .../{no => ext}/CollationData_no.java | 2 +- .../{pl => ext}/CollationData_pl.java | 2 +- .../{ro => ext}/CollationData_ro.java | 2 +- .../{ru => ext}/CollationData_ru.java | 2 +- .../{sk => ext}/CollationData_sk.java | 2 +- .../{sl => ext}/CollationData_sl.java | 2 +- .../{sq => ext}/CollationData_sq.java | 2 +- .../{sr => ext}/CollationData_sr.java | 2 +- .../{sr => ext}/CollationData_sr_Latn.java | 2 +- .../{sv => ext}/CollationData_sv.java | 2 +- .../{th => ext}/CollationData_th.java | 2 +- .../{tr => ext}/CollationData_tr.java | 2 +- .../{uk => ext}/CollationData_uk.java | 2 +- .../{vi => ext}/CollationData_vi.java | 2 +- .../{zh => ext}/CollationData_zh.java | 2 +- .../{zh/HK => ext}/CollationData_zh_HK.java | 2 +- .../{zh/TW => ext}/CollationData_zh_TW.java | 2 +- .../resources/{ar => ext}/FormatData_ar.java | 2 +- .../{ar/JO => ext}/FormatData_ar_JO.java | 2 +- .../{ar/LB => ext}/FormatData_ar_LB.java | 2 +- .../{ar/SY => ext}/FormatData_ar_SY.java | 2 +- .../resources/{be => ext}/FormatData_be.java | 2 +- .../{be/BY => ext}/FormatData_be_BY.java | 2 +- .../resources/{bg => ext}/FormatData_bg.java | 2 +- .../{bg/BG => ext}/FormatData_bg_BG.java | 2 +- .../resources/{ca => ext}/FormatData_ca.java | 2 +- .../{ca/ES => ext}/FormatData_ca_ES.java | 2 +- .../resources/{cs => ext}/FormatData_cs.java | 2 +- .../{cs/CZ => ext}/FormatData_cs_CZ.java | 2 +- .../resources/{da => ext}/FormatData_da.java | 2 +- .../{da/DK => ext}/FormatData_da_DK.java | 2 +- .../resources/{de => ext}/FormatData_de.java | 2 +- .../{de/AT => ext}/FormatData_de_AT.java | 2 +- .../{de/CH => ext}/FormatData_de_CH.java | 2 +- .../{de/DE => ext}/FormatData_de_DE.java | 2 +- .../{de/LU => ext}/FormatData_de_LU.java | 2 +- .../resources/{el => ext}/FormatData_el.java | 2 +- .../{el/CY => ext}/FormatData_el_CY.java | 2 +- .../{el/GR => ext}/FormatData_el_GR.java | 2 +- .../{en/AU => ext}/FormatData_en_AU.java | 2 +- .../{en/CA => ext}/FormatData_en_CA.java | 2 +- .../{en/GB => ext}/FormatData_en_GB.java | 2 +- .../{en/IE => ext}/FormatData_en_IE.java | 2 +- .../{en/IN => ext}/FormatData_en_IN.java | 2 +- .../{en/MT => ext}/FormatData_en_MT.java | 2 +- .../{en/NZ => ext}/FormatData_en_NZ.java | 2 +- .../{en/PH => ext}/FormatData_en_PH.java | 2 +- .../{en/SG => ext}/FormatData_en_SG.java | 2 +- .../{en/ZA => ext}/FormatData_en_ZA.java | 2 +- .../resources/{es => ext}/FormatData_es.java | 2 +- .../{es/AR => ext}/FormatData_es_AR.java | 2 +- .../{es/BO => ext}/FormatData_es_BO.java | 2 +- .../{es/CL => ext}/FormatData_es_CL.java | 2 +- .../{es/CO => ext}/FormatData_es_CO.java | 2 +- .../{es/CR => ext}/FormatData_es_CR.java | 2 +- .../{es/DO => ext}/FormatData_es_DO.java | 2 +- .../{es/EC => ext}/FormatData_es_EC.java | 2 +- .../{es/ES => ext}/FormatData_es_ES.java | 2 +- .../{es/GT => ext}/FormatData_es_GT.java | 2 +- .../{es/HN => ext}/FormatData_es_HN.java | 2 +- .../{es/MX => ext}/FormatData_es_MX.java | 2 +- .../{es/NI => ext}/FormatData_es_NI.java | 2 +- .../{es/PA => ext}/FormatData_es_PA.java | 2 +- .../{es/PE => ext}/FormatData_es_PE.java | 2 +- .../{es/PR => ext}/FormatData_es_PR.java | 2 +- .../{es/PY => ext}/FormatData_es_PY.java | 2 +- .../{es/SV => ext}/FormatData_es_SV.java | 2 +- .../{es/US => ext}/FormatData_es_US.java | 2 +- .../{es/UY => ext}/FormatData_es_UY.java | 2 +- .../{es/VE => ext}/FormatData_es_VE.java | 2 +- .../resources/{et => ext}/FormatData_et.java | 2 +- .../{et/EE => ext}/FormatData_et_EE.java | 2 +- .../resources/{fi => ext}/FormatData_fi.java | 2 +- .../{fi/FI => ext}/FormatData_fi_FI.java | 2 +- .../resources/{fr => ext}/FormatData_fr.java | 2 +- .../{fr/BE => ext}/FormatData_fr_BE.java | 2 +- .../{fr/CA => ext}/FormatData_fr_CA.java | 2 +- .../{fr/CH => ext}/FormatData_fr_CH.java | 2 +- .../{fr/FR => ext}/FormatData_fr_FR.java | 2 +- .../resources/{ga => ext}/FormatData_ga.java | 2 +- .../{ga/IE => ext}/FormatData_ga_IE.java | 2 +- .../{hi/IN => ext}/FormatData_hi_IN.java | 2 +- .../resources/{hr => ext}/FormatData_hr.java | 2 +- .../{hr/HR => ext}/FormatData_hr_HR.java | 2 +- .../resources/{hu => ext}/FormatData_hu.java | 2 +- .../{hu/HU => ext}/FormatData_hu_HU.java | 2 +- .../resources/{in => ext}/FormatData_in.java | 2 +- .../{in/ID => ext}/FormatData_in_ID.java | 2 +- .../resources/{is => ext}/FormatData_is.java | 2 +- .../{is/IS => ext}/FormatData_is_IS.java | 2 +- .../resources/{it => ext}/FormatData_it.java | 2 +- .../{it/CH => ext}/FormatData_it_CH.java | 2 +- .../{it/IT => ext}/FormatData_it_IT.java | 2 +- .../resources/{iw => ext}/FormatData_iw.java | 2 +- .../{iw/IL => ext}/FormatData_iw_IL.java | 2 +- .../resources/{ja => ext}/FormatData_ja.java | 2 +- .../{ja/JP => ext}/FormatData_ja_JP.java | 2 +- .../resources/{ko => ext}/FormatData_ko.java | 2 +- .../{ko/KR => ext}/FormatData_ko_KR.java | 2 +- .../resources/{lt => ext}/FormatData_lt.java | 2 +- .../{lt/LT => ext}/FormatData_lt_LT.java | 2 +- .../resources/{lv => ext}/FormatData_lv.java | 2 +- .../{lv/LV => ext}/FormatData_lv_LV.java | 2 +- .../resources/{mk => ext}/FormatData_mk.java | 2 +- .../{mk/MK => ext}/FormatData_mk_MK.java | 2 +- .../resources/{ms => ext}/FormatData_ms.java | 2 +- .../{ms/MY => ext}/FormatData_ms_MY.java | 2 +- .../resources/{mt => ext}/FormatData_mt.java | 2 +- .../{mt/MT => ext}/FormatData_mt_MT.java | 2 +- .../resources/{nl => ext}/FormatData_nl.java | 2 +- .../{nl/BE => ext}/FormatData_nl_BE.java | 2 +- .../{nl/NL => ext}/FormatData_nl_NL.java | 2 +- .../resources/{no => ext}/FormatData_no.java | 2 +- .../{no/NO => ext}/FormatData_no_NO.java | 2 +- .../{no/NO => ext}/FormatData_no_NO_NY.java | 2 +- .../resources/{pl => ext}/FormatData_pl.java | 2 +- .../{pl/PL => ext}/FormatData_pl_PL.java | 2 +- .../resources/{pt => ext}/FormatData_pt.java | 2 +- .../{pt/BR => ext}/FormatData_pt_BR.java | 2 +- .../{pt/PT => ext}/FormatData_pt_PT.java | 2 +- .../resources/{ro => ext}/FormatData_ro.java | 2 +- .../{ro/RO => ext}/FormatData_ro_RO.java | 2 +- .../resources/{ru => ext}/FormatData_ru.java | 2 +- .../{ru/RU => ext}/FormatData_ru_RU.java | 2 +- .../resources/{sk => ext}/FormatData_sk.java | 2 +- .../{sk/SK => ext}/FormatData_sk_SK.java | 2 +- .../resources/{sl => ext}/FormatData_sl.java | 2 +- .../{sl/SI => ext}/FormatData_sl_SI.java | 2 +- .../resources/{sq => ext}/FormatData_sq.java | 2 +- .../{sq/AL => ext}/FormatData_sq_AL.java | 2 +- .../resources/{sr => ext}/FormatData_sr.java | 2 +- .../{sr/BA => ext}/FormatData_sr_BA.java | 2 +- .../{sr/CS => ext}/FormatData_sr_CS.java | 2 +- .../{sr => ext}/FormatData_sr_Latn.java | 2 +- .../{sr/ME => ext}/FormatData_sr_Latn_ME.java | 2 +- .../{sr/ME => ext}/FormatData_sr_ME.java | 2 +- .../{sr/RS => ext}/FormatData_sr_RS.java | 2 +- .../resources/{sv => ext}/FormatData_sv.java | 2 +- .../{sv/SE => ext}/FormatData_sv_SE.java | 2 +- .../resources/{th => ext}/FormatData_th.java | 2 +- .../{th/TH => ext}/FormatData_th_TH.java | 2 +- .../resources/{tr => ext}/FormatData_tr.java | 2 +- .../{tr/TR => ext}/FormatData_tr_TR.java | 2 +- .../resources/{uk => ext}/FormatData_uk.java | 2 +- .../{uk/UA => ext}/FormatData_uk_UA.java | 2 +- .../resources/{vi => ext}/FormatData_vi.java | 2 +- .../{vi/VN => ext}/FormatData_vi_VN.java | 2 +- .../resources/{zh => ext}/FormatData_zh.java | 2 +- .../{zh/CN => ext}/FormatData_zh_CN.java | 2 +- .../{zh/HK => ext}/FormatData_zh_HK.java | 2 +- .../{zh/SG => ext}/FormatData_zh_SG.java | 2 +- .../{zh/TW => ext}/FormatData_zh_TW.java | 2 +- .../{ar => ext}/JavaTimeSupplementary_ar.java | 2 +- .../JavaTimeSupplementary_ar_JO.java | 2 +- .../JavaTimeSupplementary_ar_LB.java | 2 +- .../JavaTimeSupplementary_ar_SY.java | 2 +- .../{be => ext}/JavaTimeSupplementary_be.java | 2 +- .../{bg => ext}/JavaTimeSupplementary_bg.java | 2 +- .../{ca => ext}/JavaTimeSupplementary_ca.java | 2 +- .../{cs => ext}/JavaTimeSupplementary_cs.java | 2 +- .../{da => ext}/JavaTimeSupplementary_da.java | 2 +- .../{de => ext}/JavaTimeSupplementary_de.java | 2 +- .../JavaTimeSupplementary_de_AT.java | 2 +- .../{el => ext}/JavaTimeSupplementary_el.java | 2 +- .../JavaTimeSupplementary_en_AU.java | 2 +- .../JavaTimeSupplementary_en_CA.java | 2 +- .../JavaTimeSupplementary_en_GB.java | 2 +- .../JavaTimeSupplementary_en_IE.java | 2 +- .../JavaTimeSupplementary_en_IN.java | 2 +- .../JavaTimeSupplementary_en_MT.java | 2 +- .../JavaTimeSupplementary_en_NZ.java | 2 +- .../JavaTimeSupplementary_en_SG.java | 2 +- .../JavaTimeSupplementary_en_ZA.java | 2 +- .../{es => ext}/JavaTimeSupplementary_es.java | 2 +- .../JavaTimeSupplementary_es_CL.java | 2 +- .../JavaTimeSupplementary_es_CO.java | 2 +- .../JavaTimeSupplementary_es_GT.java | 2 +- .../JavaTimeSupplementary_es_HN.java | 2 +- .../JavaTimeSupplementary_es_MX.java | 2 +- .../JavaTimeSupplementary_es_PA.java | 2 +- .../JavaTimeSupplementary_es_PE.java | 2 +- .../JavaTimeSupplementary_es_PR.java | 2 +- .../JavaTimeSupplementary_es_UY.java | 2 +- .../{et => ext}/JavaTimeSupplementary_et.java | 2 +- .../{fi => ext}/JavaTimeSupplementary_fi.java | 2 +- .../{fr => ext}/JavaTimeSupplementary_fr.java | 2 +- .../JavaTimeSupplementary_fr_BE.java | 2 +- .../JavaTimeSupplementary_fr_CA.java | 2 +- .../JavaTimeSupplementary_fr_CH.java | 2 +- .../{ga => ext}/JavaTimeSupplementary_ga.java | 2 +- .../JavaTimeSupplementary_hi_IN.java | 2 +- .../{hr => ext}/JavaTimeSupplementary_hr.java | 2 +- .../{hu => ext}/JavaTimeSupplementary_hu.java | 2 +- .../{is => ext}/JavaTimeSupplementary_is.java | 2 +- .../{it => ext}/JavaTimeSupplementary_it.java | 2 +- .../JavaTimeSupplementary_it_CH.java | 2 +- .../{iw => ext}/JavaTimeSupplementary_iw.java | 2 +- .../JavaTimeSupplementary_iw_IL.java | 2 +- .../{ja => ext}/JavaTimeSupplementary_ja.java | 2 +- .../{ko => ext}/JavaTimeSupplementary_ko.java | 2 +- .../{lt => ext}/JavaTimeSupplementary_lt.java | 2 +- .../{lv => ext}/JavaTimeSupplementary_lv.java | 2 +- .../{mk => ext}/JavaTimeSupplementary_mk.java | 2 +- .../{ms => ext}/JavaTimeSupplementary_ms.java | 2 +- .../{mt => ext}/JavaTimeSupplementary_mt.java | 2 +- .../{nl => ext}/JavaTimeSupplementary_nl.java | 2 +- .../JavaTimeSupplementary_nl_BE.java | 2 +- .../{no => ext}/JavaTimeSupplementary_no.java | 2 +- .../{pl => ext}/JavaTimeSupplementary_pl.java | 2 +- .../{pt => ext}/JavaTimeSupplementary_pt.java | 2 +- .../JavaTimeSupplementary_pt_PT.java | 2 +- .../{ro => ext}/JavaTimeSupplementary_ro.java | 2 +- .../{ru => ext}/JavaTimeSupplementary_ru.java | 2 +- .../{sk => ext}/JavaTimeSupplementary_sk.java | 2 +- .../{sl => ext}/JavaTimeSupplementary_sl.java | 2 +- .../{sq => ext}/JavaTimeSupplementary_sq.java | 2 +- .../{sr => ext}/JavaTimeSupplementary_sr.java | 2 +- .../JavaTimeSupplementary_sr_Latn.java | 2 +- .../{sv => ext}/JavaTimeSupplementary_sv.java | 2 +- .../{th => ext}/JavaTimeSupplementary_th.java | 2 +- .../{tr => ext}/JavaTimeSupplementary_tr.java | 2 +- .../{uk => ext}/JavaTimeSupplementary_uk.java | 2 +- .../{vi => ext}/JavaTimeSupplementary_vi.java | 2 +- .../{zh => ext}/JavaTimeSupplementary_zh.java | 2 +- .../JavaTimeSupplementary_zh_TW.java | 2 +- .../sun/text/resources/{th => }/thai_dict | Bin .../{ar => ext}/CalendarData_ar.properties | 0 .../{be => ext}/CalendarData_be.properties | 0 .../{bg => ext}/CalendarData_bg.properties | 0 .../{ca => ext}/CalendarData_ca.properties | 0 .../{cs => ext}/CalendarData_cs.properties | 0 .../{da => ext}/CalendarData_da.properties | 0 .../{de => ext}/CalendarData_de.properties | 0 .../{el => ext}/CalendarData_el.properties | 0 .../CY => ext}/CalendarData_el_CY.properties | 0 .../GB => ext}/CalendarData_en_GB.properties | 0 .../IE => ext}/CalendarData_en_IE.properties | 0 .../MT => ext}/CalendarData_en_MT.properties | 0 .../{es => ext}/CalendarData_es.properties | 0 .../ES => ext}/CalendarData_es_ES.properties | 0 .../US => ext}/CalendarData_es_US.properties | 0 .../{et => ext}/CalendarData_et.properties | 0 .../{fi => ext}/CalendarData_fi.properties | 0 .../{fr => ext}/CalendarData_fr.properties | 0 .../CA => ext}/CalendarData_fr_CA.properties | 0 .../{hi => ext}/CalendarData_hi.properties | 0 .../{hr => ext}/CalendarData_hr.properties | 0 .../{hu => ext}/CalendarData_hu.properties | 0 .../ID => ext}/CalendarData_in_ID.properties | 0 .../{is => ext}/CalendarData_is.properties | 0 .../{it => ext}/CalendarData_it.properties | 0 .../{iw => ext}/CalendarData_iw.properties | 0 .../{ja => ext}/CalendarData_ja.properties | 0 .../{ko => ext}/CalendarData_ko.properties | 0 .../{lt => ext}/CalendarData_lt.properties | 0 .../{lv => ext}/CalendarData_lv.properties | 0 .../{mk => ext}/CalendarData_mk.properties | 0 .../MY => ext}/CalendarData_ms_MY.properties | 0 .../{mt => ext}/CalendarData_mt.properties | 0 .../MT => ext}/CalendarData_mt_MT.properties | 0 .../{nl => ext}/CalendarData_nl.properties | 0 .../{no => ext}/CalendarData_no.properties | 0 .../{pl => ext}/CalendarData_pl.properties | 0 .../{pt => ext}/CalendarData_pt.properties | 0 .../BR => ext}/CalendarData_pt_BR.properties | 0 .../PT => ext}/CalendarData_pt_PT.properties | 0 .../{ro => ext}/CalendarData_ro.properties | 0 .../{ru => ext}/CalendarData_ru.properties | 0 .../{sk => ext}/CalendarData_sk.properties | 0 .../{sl => ext}/CalendarData_sl.properties | 0 .../{sq => ext}/CalendarData_sq.properties | 0 .../{sr => ext}/CalendarData_sr.properties | 0 .../CalendarData_sr_Latn_BA.properties | 0 .../CalendarData_sr_Latn_ME.properties | 0 .../CalendarData_sr_Latn_RS.properties | 0 .../{sv => ext}/CalendarData_sv.properties | 0 .../{th => ext}/CalendarData_th.properties | 0 .../{tr => ext}/CalendarData_tr.properties | 0 .../{uk => ext}/CalendarData_uk.properties | 0 .../{vi => ext}/CalendarData_vi.properties | 0 .../{zh => ext}/CalendarData_zh.properties | 0 .../AE => ext}/CurrencyNames_ar_AE.properties | 0 .../BH => ext}/CurrencyNames_ar_BH.properties | 0 .../DZ => ext}/CurrencyNames_ar_DZ.properties | 0 .../EG => ext}/CurrencyNames_ar_EG.properties | 0 .../IQ => ext}/CurrencyNames_ar_IQ.properties | 0 .../JO => ext}/CurrencyNames_ar_JO.properties | 0 .../KW => ext}/CurrencyNames_ar_KW.properties | 0 .../LB => ext}/CurrencyNames_ar_LB.properties | 0 .../LY => ext}/CurrencyNames_ar_LY.properties | 0 .../MA => ext}/CurrencyNames_ar_MA.properties | 0 .../OM => ext}/CurrencyNames_ar_OM.properties | 0 .../QA => ext}/CurrencyNames_ar_QA.properties | 0 .../SA => ext}/CurrencyNames_ar_SA.properties | 0 .../SD => ext}/CurrencyNames_ar_SD.properties | 0 .../SY => ext}/CurrencyNames_ar_SY.properties | 0 .../TN => ext}/CurrencyNames_ar_TN.properties | 0 .../YE => ext}/CurrencyNames_ar_YE.properties | 0 .../BY => ext}/CurrencyNames_be_BY.properties | 0 .../BG => ext}/CurrencyNames_bg_BG.properties | 0 .../ES => ext}/CurrencyNames_ca_ES.properties | 0 .../CZ => ext}/CurrencyNames_cs_CZ.properties | 0 .../DK => ext}/CurrencyNames_da_DK.properties | 0 .../{de => ext}/CurrencyNames_de.properties | 0 .../AT => ext}/CurrencyNames_de_AT.properties | 0 .../CH => ext}/CurrencyNames_de_CH.properties | 0 .../DE => ext}/CurrencyNames_de_DE.properties | 0 .../GR => ext}/CurrencyNames_de_GR.properties | 0 .../LU => ext}/CurrencyNames_de_LU.properties | 0 .../CY => ext}/CurrencyNames_el_CY.properties | 0 .../GR => ext}/CurrencyNames_el_GR.properties | 0 .../AU => ext}/CurrencyNames_en_AU.properties | 0 .../CA => ext}/CurrencyNames_en_CA.properties | 0 .../GB => ext}/CurrencyNames_en_GB.properties | 0 .../IE => ext}/CurrencyNames_en_IE.properties | 0 .../IN => ext}/CurrencyNames_en_IN.properties | 0 .../MT => ext}/CurrencyNames_en_MT.properties | 0 .../NZ => ext}/CurrencyNames_en_NZ.properties | 0 .../PH => ext}/CurrencyNames_en_PH.properties | 0 .../SG => ext}/CurrencyNames_en_SG.properties | 0 .../ZA => ext}/CurrencyNames_en_ZA.properties | 0 .../{es => ext}/CurrencyNames_es.properties | 0 .../AR => ext}/CurrencyNames_es_AR.properties | 0 .../BO => ext}/CurrencyNames_es_BO.properties | 0 .../CL => ext}/CurrencyNames_es_CL.properties | 0 .../CO => ext}/CurrencyNames_es_CO.properties | 0 .../CR => ext}/CurrencyNames_es_CR.properties | 0 .../CU => ext}/CurrencyNames_es_CU.properties | 0 .../DO => ext}/CurrencyNames_es_DO.properties | 0 .../EC => ext}/CurrencyNames_es_EC.properties | 0 .../ES => ext}/CurrencyNames_es_ES.properties | 0 .../GT => ext}/CurrencyNames_es_GT.properties | 0 .../HN => ext}/CurrencyNames_es_HN.properties | 0 .../MX => ext}/CurrencyNames_es_MX.properties | 0 .../NI => ext}/CurrencyNames_es_NI.properties | 0 .../PA => ext}/CurrencyNames_es_PA.properties | 0 .../PE => ext}/CurrencyNames_es_PE.properties | 0 .../PR => ext}/CurrencyNames_es_PR.properties | 0 .../PY => ext}/CurrencyNames_es_PY.properties | 0 .../SV => ext}/CurrencyNames_es_SV.properties | 0 .../US => ext}/CurrencyNames_es_US.properties | 0 .../UY => ext}/CurrencyNames_es_UY.properties | 0 .../VE => ext}/CurrencyNames_es_VE.properties | 0 .../EE => ext}/CurrencyNames_et_EE.properties | 0 .../FI => ext}/CurrencyNames_fi_FI.properties | 0 .../{fr => ext}/CurrencyNames_fr.properties | 0 .../BE => ext}/CurrencyNames_fr_BE.properties | 0 .../CA => ext}/CurrencyNames_fr_CA.properties | 0 .../CH => ext}/CurrencyNames_fr_CH.properties | 0 .../FR => ext}/CurrencyNames_fr_FR.properties | 0 .../LU => ext}/CurrencyNames_fr_LU.properties | 0 .../IE => ext}/CurrencyNames_ga_IE.properties | 0 .../IN => ext}/CurrencyNames_hi_IN.properties | 0 .../HR => ext}/CurrencyNames_hr_HR.properties | 0 .../HU => ext}/CurrencyNames_hu_HU.properties | 0 .../ID => ext}/CurrencyNames_in_ID.properties | 0 .../IS => ext}/CurrencyNames_is_IS.properties | 0 .../{it => ext}/CurrencyNames_it.properties | 0 .../CH => ext}/CurrencyNames_it_CH.properties | 0 .../IT => ext}/CurrencyNames_it_IT.properties | 0 .../IL => ext}/CurrencyNames_iw_IL.properties | 0 .../{ja => ext}/CurrencyNames_ja.properties | 0 .../JP => ext}/CurrencyNames_ja_JP.properties | 0 .../{ko => ext}/CurrencyNames_ko.properties | 0 .../KR => ext}/CurrencyNames_ko_KR.properties | 0 .../LT => ext}/CurrencyNames_lt_LT.properties | 0 .../LV => ext}/CurrencyNames_lv_LV.properties | 0 .../MK => ext}/CurrencyNames_mk_MK.properties | 0 .../MY => ext}/CurrencyNames_ms_MY.properties | 0 .../MT => ext}/CurrencyNames_mt_MT.properties | 0 .../BE => ext}/CurrencyNames_nl_BE.properties | 0 .../NL => ext}/CurrencyNames_nl_NL.properties | 0 .../NO => ext}/CurrencyNames_no_NO.properties | 0 .../PL => ext}/CurrencyNames_pl_PL.properties | 0 .../{pt => ext}/CurrencyNames_pt.properties | 0 .../BR => ext}/CurrencyNames_pt_BR.properties | 0 .../PT => ext}/CurrencyNames_pt_PT.properties | 0 .../RO => ext}/CurrencyNames_ro_RO.properties | 0 .../RU => ext}/CurrencyNames_ru_RU.properties | 0 .../SK => ext}/CurrencyNames_sk_SK.properties | 0 .../SI => ext}/CurrencyNames_sl_SI.properties | 0 .../AL => ext}/CurrencyNames_sq_AL.properties | 0 .../BA => ext}/CurrencyNames_sr_BA.properties | 0 .../CS => ext}/CurrencyNames_sr_CS.properties | 0 .../CurrencyNames_sr_Latn_BA.properties | 0 .../CurrencyNames_sr_Latn_ME.properties | 0 .../CurrencyNames_sr_Latn_RS.properties | 0 .../ME => ext}/CurrencyNames_sr_ME.properties | 0 .../RS => ext}/CurrencyNames_sr_RS.properties | 0 .../{sv => ext}/CurrencyNames_sv.properties | 0 .../SE => ext}/CurrencyNames_sv_SE.properties | 0 .../TH => ext}/CurrencyNames_th_TH.properties | 0 .../TR => ext}/CurrencyNames_tr_TR.properties | 0 .../UA => ext}/CurrencyNames_uk_UA.properties | 0 .../VN => ext}/CurrencyNames_vi_VN.properties | 0 .../CN => ext}/CurrencyNames_zh_CN.properties | 0 .../{zh/HK => ext}/CurrencyNames_zh_HK.java | 2 +- .../{zh/SG => ext}/CurrencyNames_zh_SG.java | 2 +- .../TW => ext}/CurrencyNames_zh_TW.properties | 0 .../{ar => ext}/LocaleNames_ar.properties | 0 .../{be => ext}/LocaleNames_be.properties | 0 .../{bg => ext}/LocaleNames_bg.properties | 0 .../{ca => ext}/LocaleNames_ca.properties | 0 .../{cs => ext}/LocaleNames_cs.properties | 0 .../{da => ext}/LocaleNames_da.properties | 0 .../{de => ext}/LocaleNames_de.properties | 0 .../{el => ext}/LocaleNames_el.properties | 0 .../CY => ext}/LocaleNames_el_CY.properties | 0 .../MT => ext}/LocaleNames_en_MT.properties | 0 .../PH => ext}/LocaleNames_en_PH.properties | 0 .../SG => ext}/LocaleNames_en_SG.properties | 0 .../{es => ext}/LocaleNames_es.properties | 0 .../US => ext}/LocaleNames_es_US.properties | 0 .../{et => ext}/LocaleNames_et.properties | 0 .../{fi => ext}/LocaleNames_fi.properties | 0 .../{fr => ext}/LocaleNames_fr.properties | 0 .../{ga => ext}/LocaleNames_ga.properties | 0 .../{hi => ext}/LocaleNames_hi.properties | 0 .../{hr => ext}/LocaleNames_hr.properties | 0 .../{hu => ext}/LocaleNames_hu.properties | 0 .../{in => ext}/LocaleNames_in.properties | 0 .../{is => ext}/LocaleNames_is.properties | 0 .../{it => ext}/LocaleNames_it.properties | 0 .../{iw => ext}/LocaleNames_iw.properties | 0 .../{ja => ext}/LocaleNames_ja.properties | 0 .../{ko => ext}/LocaleNames_ko.properties | 0 .../{lt => ext}/LocaleNames_lt.properties | 0 .../{lv => ext}/LocaleNames_lv.properties | 0 .../{mk => ext}/LocaleNames_mk.properties | 0 .../{ms => ext}/LocaleNames_ms.properties | 0 .../{mt => ext}/LocaleNames_mt.properties | 0 .../{nl => ext}/LocaleNames_nl.properties | 0 .../{no => ext}/LocaleNames_no.properties | 0 .../LocaleNames_no_NO_NY.properties | 0 .../{pl => ext}/LocaleNames_pl.properties | 0 .../{pt => ext}/LocaleNames_pt.properties | 0 .../BR => ext}/LocaleNames_pt_BR.properties | 0 .../PT => ext}/LocaleNames_pt_PT.properties | 0 .../{ro => ext}/LocaleNames_ro.properties | 0 .../{ru => ext}/LocaleNames_ru.properties | 0 .../{sk => ext}/LocaleNames_sk.properties | 0 .../{sl => ext}/LocaleNames_sl.properties | 0 .../{sq => ext}/LocaleNames_sq.properties | 0 .../{sr => ext}/LocaleNames_sr.properties | 0 .../LocaleNames_sr_Latn.properties | 0 .../{sv => ext}/LocaleNames_sv.properties | 0 .../{th => ext}/LocaleNames_th.properties | 0 .../{tr => ext}/LocaleNames_tr.properties | 0 .../{uk => ext}/LocaleNames_uk.properties | 0 .../{vi => ext}/LocaleNames_vi.properties | 0 .../{zh => ext}/LocaleNames_zh.properties | 0 .../{zh/HK => ext}/LocaleNames_zh_HK.java | 2 +- .../SG => ext}/LocaleNames_zh_SG.properties | 0 .../TW => ext}/LocaleNames_zh_TW.properties | 0 .../{de => ext}/TimeZoneNames_de.java | 2 +- .../{en/CA => ext}/TimeZoneNames_en_CA.java | 2 +- .../{en/GB => ext}/TimeZoneNames_en_GB.java | 2 +- .../{en/IE => ext}/TimeZoneNames_en_IE.java | 2 +- .../{es => ext}/TimeZoneNames_es.java | 2 +- .../{fr => ext}/TimeZoneNames_fr.java | 2 +- .../{hi => ext}/TimeZoneNames_hi.java | 2 +- .../{it => ext}/TimeZoneNames_it.java | 2 +- .../{ja => ext}/TimeZoneNames_ja.java | 2 +- .../{ko => ext}/TimeZoneNames_ko.java | 2 +- .../{pt/BR => ext}/TimeZoneNames_pt_BR.java | 2 +- .../{sv => ext}/TimeZoneNames_sv.java | 2 +- .../{zh/CN => ext}/TimeZoneNames_zh_CN.java | 2 +- .../{zh/HK => ext}/TimeZoneNames_zh_HK.java | 2 +- .../{zh/TW => ext}/TimeZoneNames_zh_TW.java | 2 +- 505 files changed, 318 insertions(+), 388 deletions(-) delete mode 100644 jdk/make/src/classes/build/tools/generatebreakiteratordata/BreakIteratorRBControl.java rename jdk/src/java.base/share/classes/sun/text/resources/{en => }/FormatData_en.java (99%) rename jdk/src/java.base/share/classes/sun/text/resources/{en/US => }/FormatData_en_US.java (98%) rename jdk/src/java.base/share/classes/sun/text/resources/{en => }/JavaTimeSupplementary_en.java (99%) rename jdk/src/java.base/share/classes/sun/util/resources/{en => }/CalendarData_en.properties (100%) rename jdk/src/java.base/share/classes/sun/util/resources/{en/US => }/CurrencyNames_en_US.properties (100%) rename jdk/src/java.base/share/classes/sun/util/resources/{en => }/LocaleNames_en.properties (100%) rename jdk/src/java.base/share/classes/sun/util/resources/{en => }/TimeZoneNames_en.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th => ext}/BreakIteratorInfo_th.java (92%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th => ext}/BreakIteratorRules_th.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar => ext}/CollationData_ar.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{be => ext}/CollationData_be.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{bg => ext}/CollationData_bg.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ca => ext}/CollationData_ca.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{cs => ext}/CollationData_cs.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{da => ext}/CollationData_da.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{el => ext}/CollationData_el.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es => ext}/CollationData_es.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{et => ext}/CollationData_et.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fi => ext}/CollationData_fi.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr => ext}/CollationData_fr.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hi => ext}/CollationData_hi.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hr => ext}/CollationData_hr.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hu => ext}/CollationData_hu.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{is => ext}/CollationData_is.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{iw => ext}/CollationData_iw.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ja => ext}/CollationData_ja.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ko => ext}/CollationData_ko.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lt => ext}/CollationData_lt.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lv => ext}/CollationData_lv.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mk => ext}/CollationData_mk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{no => ext}/CollationData_no.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pl => ext}/CollationData_pl.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ro => ext}/CollationData_ro.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ru => ext}/CollationData_ru.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sk => ext}/CollationData_sk.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sl => ext}/CollationData_sl.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sq => ext}/CollationData_sq.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr => ext}/CollationData_sr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr => ext}/CollationData_sr_Latn.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sv => ext}/CollationData_sv.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th => ext}/CollationData_th.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{tr => ext}/CollationData_tr.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{uk => ext}/CollationData_uk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{vi => ext}/CollationData_vi.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh => ext}/CollationData_zh.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/HK => ext}/CollationData_zh_HK.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/TW => ext}/CollationData_zh_TW.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar => ext}/FormatData_ar.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar/JO => ext}/FormatData_ar_JO.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar/LB => ext}/FormatData_ar_LB.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar/SY => ext}/FormatData_ar_SY.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{be => ext}/FormatData_be.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{be/BY => ext}/FormatData_be_BY.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{bg => ext}/FormatData_bg.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{bg/BG => ext}/FormatData_bg_BG.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ca => ext}/FormatData_ca.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ca/ES => ext}/FormatData_ca_ES.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{cs => ext}/FormatData_cs.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{cs/CZ => ext}/FormatData_cs_CZ.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{da => ext}/FormatData_da.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{da/DK => ext}/FormatData_da_DK.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de => ext}/FormatData_de.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de/AT => ext}/FormatData_de_AT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de/CH => ext}/FormatData_de_CH.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de/DE => ext}/FormatData_de_DE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de/LU => ext}/FormatData_de_LU.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{el => ext}/FormatData_el.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{el/CY => ext}/FormatData_el_CY.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{el/GR => ext}/FormatData_el_GR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/AU => ext}/FormatData_en_AU.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/CA => ext}/FormatData_en_CA.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/GB => ext}/FormatData_en_GB.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/IE => ext}/FormatData_en_IE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/IN => ext}/FormatData_en_IN.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/MT => ext}/FormatData_en_MT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/NZ => ext}/FormatData_en_NZ.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/PH => ext}/FormatData_en_PH.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/SG => ext}/FormatData_en_SG.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/ZA => ext}/FormatData_en_ZA.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es => ext}/FormatData_es.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/AR => ext}/FormatData_es_AR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/BO => ext}/FormatData_es_BO.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/CL => ext}/FormatData_es_CL.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/CO => ext}/FormatData_es_CO.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/CR => ext}/FormatData_es_CR.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/DO => ext}/FormatData_es_DO.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/EC => ext}/FormatData_es_EC.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/ES => ext}/FormatData_es_ES.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/GT => ext}/FormatData_es_GT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/HN => ext}/FormatData_es_HN.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/MX => ext}/FormatData_es_MX.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/NI => ext}/FormatData_es_NI.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PA => ext}/FormatData_es_PA.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PE => ext}/FormatData_es_PE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PR => ext}/FormatData_es_PR.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PY => ext}/FormatData_es_PY.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/SV => ext}/FormatData_es_SV.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/US => ext}/FormatData_es_US.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/UY => ext}/FormatData_es_UY.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/VE => ext}/FormatData_es_VE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{et => ext}/FormatData_et.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{et/EE => ext}/FormatData_et_EE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fi => ext}/FormatData_fi.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fi/FI => ext}/FormatData_fi_FI.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr => ext}/FormatData_fr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/BE => ext}/FormatData_fr_BE.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/CA => ext}/FormatData_fr_CA.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/CH => ext}/FormatData_fr_CH.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/FR => ext}/FormatData_fr_FR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ga => ext}/FormatData_ga.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ga/IE => ext}/FormatData_ga_IE.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hi/IN => ext}/FormatData_hi_IN.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hr => ext}/FormatData_hr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hr/HR => ext}/FormatData_hr_HR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hu => ext}/FormatData_hu.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hu/HU => ext}/FormatData_hu_HU.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{in => ext}/FormatData_in.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{in/ID => ext}/FormatData_in_ID.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{is => ext}/FormatData_is.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{is/IS => ext}/FormatData_is_IS.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{it => ext}/FormatData_it.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{it/CH => ext}/FormatData_it_CH.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{it/IT => ext}/FormatData_it_IT.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{iw => ext}/FormatData_iw.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{iw/IL => ext}/FormatData_iw_IL.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ja => ext}/FormatData_ja.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ja/JP => ext}/FormatData_ja_JP.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ko => ext}/FormatData_ko.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ko/KR => ext}/FormatData_ko_KR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lt => ext}/FormatData_lt.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lt/LT => ext}/FormatData_lt_LT.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lv => ext}/FormatData_lv.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lv/LV => ext}/FormatData_lv_LV.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mk => ext}/FormatData_mk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mk/MK => ext}/FormatData_mk_MK.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ms => ext}/FormatData_ms.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ms/MY => ext}/FormatData_ms_MY.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mt => ext}/FormatData_mt.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mt/MT => ext}/FormatData_mt_MT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{nl => ext}/FormatData_nl.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{nl/BE => ext}/FormatData_nl_BE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{nl/NL => ext}/FormatData_nl_NL.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{no => ext}/FormatData_no.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{no/NO => ext}/FormatData_no_NO.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{no/NO => ext}/FormatData_no_NO_NY.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pl => ext}/FormatData_pl.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pl/PL => ext}/FormatData_pl_PL.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pt => ext}/FormatData_pt.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pt/BR => ext}/FormatData_pt_BR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pt/PT => ext}/FormatData_pt_PT.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ro => ext}/FormatData_ro.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ro/RO => ext}/FormatData_ro_RO.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ru => ext}/FormatData_ru.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ru/RU => ext}/FormatData_ru_RU.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sk => ext}/FormatData_sk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sk/SK => ext}/FormatData_sk_SK.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sl => ext}/FormatData_sl.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sl/SI => ext}/FormatData_sl_SI.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sq => ext}/FormatData_sq.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sq/AL => ext}/FormatData_sq_AL.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr => ext}/FormatData_sr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr/BA => ext}/FormatData_sr_BA.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr/CS => ext}/FormatData_sr_CS.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr => ext}/FormatData_sr_Latn.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr/ME => ext}/FormatData_sr_Latn_ME.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr/ME => ext}/FormatData_sr_ME.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr/RS => ext}/FormatData_sr_RS.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sv => ext}/FormatData_sv.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sv/SE => ext}/FormatData_sv_SE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th => ext}/FormatData_th.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th/TH => ext}/FormatData_th_TH.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{tr => ext}/FormatData_tr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{tr/TR => ext}/FormatData_tr_TR.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{uk => ext}/FormatData_uk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{uk/UA => ext}/FormatData_uk_UA.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{vi => ext}/FormatData_vi.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{vi/VN => ext}/FormatData_vi_VN.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh => ext}/FormatData_zh.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/CN => ext}/FormatData_zh_CN.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/HK => ext}/FormatData_zh_HK.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/SG => ext}/FormatData_zh_SG.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/TW => ext}/FormatData_zh_TW.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar => ext}/JavaTimeSupplementary_ar.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar/JO => ext}/JavaTimeSupplementary_ar_JO.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar/LB => ext}/JavaTimeSupplementary_ar_LB.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ar/SY => ext}/JavaTimeSupplementary_ar_SY.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{be => ext}/JavaTimeSupplementary_be.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{bg => ext}/JavaTimeSupplementary_bg.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ca => ext}/JavaTimeSupplementary_ca.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{cs => ext}/JavaTimeSupplementary_cs.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{da => ext}/JavaTimeSupplementary_da.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de => ext}/JavaTimeSupplementary_de.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{de/AT => ext}/JavaTimeSupplementary_de_AT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{el => ext}/JavaTimeSupplementary_el.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/AU => ext}/JavaTimeSupplementary_en_AU.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/CA => ext}/JavaTimeSupplementary_en_CA.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/GB => ext}/JavaTimeSupplementary_en_GB.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/IE => ext}/JavaTimeSupplementary_en_IE.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/IN => ext}/JavaTimeSupplementary_en_IN.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/MT => ext}/JavaTimeSupplementary_en_MT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/NZ => ext}/JavaTimeSupplementary_en_NZ.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/SG => ext}/JavaTimeSupplementary_en_SG.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{en/ZA => ext}/JavaTimeSupplementary_en_ZA.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es => ext}/JavaTimeSupplementary_es.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/CL => ext}/JavaTimeSupplementary_es_CL.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/CO => ext}/JavaTimeSupplementary_es_CO.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/GT => ext}/JavaTimeSupplementary_es_GT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/HN => ext}/JavaTimeSupplementary_es_HN.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/MX => ext}/JavaTimeSupplementary_es_MX.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PA => ext}/JavaTimeSupplementary_es_PA.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PE => ext}/JavaTimeSupplementary_es_PE.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/PR => ext}/JavaTimeSupplementary_es_PR.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{es/UY => ext}/JavaTimeSupplementary_es_UY.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{et => ext}/JavaTimeSupplementary_et.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fi => ext}/JavaTimeSupplementary_fi.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr => ext}/JavaTimeSupplementary_fr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/BE => ext}/JavaTimeSupplementary_fr_BE.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/CA => ext}/JavaTimeSupplementary_fr_CA.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{fr/CH => ext}/JavaTimeSupplementary_fr_CH.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ga => ext}/JavaTimeSupplementary_ga.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hi/IN => ext}/JavaTimeSupplementary_hi_IN.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hr => ext}/JavaTimeSupplementary_hr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{hu => ext}/JavaTimeSupplementary_hu.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{is => ext}/JavaTimeSupplementary_is.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{it => ext}/JavaTimeSupplementary_it.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{it/CH => ext}/JavaTimeSupplementary_it_CH.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{iw => ext}/JavaTimeSupplementary_iw.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{iw/IL => ext}/JavaTimeSupplementary_iw_IL.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ja => ext}/JavaTimeSupplementary_ja.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ko => ext}/JavaTimeSupplementary_ko.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lt => ext}/JavaTimeSupplementary_lt.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{lv => ext}/JavaTimeSupplementary_lv.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mk => ext}/JavaTimeSupplementary_mk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ms => ext}/JavaTimeSupplementary_ms.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{mt => ext}/JavaTimeSupplementary_mt.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{nl => ext}/JavaTimeSupplementary_nl.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{nl/BE => ext}/JavaTimeSupplementary_nl_BE.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{no => ext}/JavaTimeSupplementary_no.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pl => ext}/JavaTimeSupplementary_pl.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pt => ext}/JavaTimeSupplementary_pt.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{pt/PT => ext}/JavaTimeSupplementary_pt_PT.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ro => ext}/JavaTimeSupplementary_ro.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{ru => ext}/JavaTimeSupplementary_ru.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sk => ext}/JavaTimeSupplementary_sk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sl => ext}/JavaTimeSupplementary_sl.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sq => ext}/JavaTimeSupplementary_sq.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr => ext}/JavaTimeSupplementary_sr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sr => ext}/JavaTimeSupplementary_sr_Latn.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{sv => ext}/JavaTimeSupplementary_sv.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th => ext}/JavaTimeSupplementary_th.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{tr => ext}/JavaTimeSupplementary_tr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{uk => ext}/JavaTimeSupplementary_uk.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{vi => ext}/JavaTimeSupplementary_vi.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh => ext}/JavaTimeSupplementary_zh.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{zh/TW => ext}/JavaTimeSupplementary_zh_TW.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/text/resources/{th => }/thai_dict (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar => ext}/CalendarData_ar.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{be => ext}/CalendarData_be.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{bg => ext}/CalendarData_bg.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ca => ext}/CalendarData_ca.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{cs => ext}/CalendarData_cs.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{da => ext}/CalendarData_da.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de => ext}/CalendarData_de.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{el => ext}/CalendarData_el.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{el/CY => ext}/CalendarData_el_CY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/GB => ext}/CalendarData_en_GB.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/IE => ext}/CalendarData_en_IE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/MT => ext}/CalendarData_en_MT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es => ext}/CalendarData_es.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/ES => ext}/CalendarData_es_ES.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/US => ext}/CalendarData_es_US.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{et => ext}/CalendarData_et.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fi => ext}/CalendarData_fi.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr => ext}/CalendarData_fr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr/CA => ext}/CalendarData_fr_CA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hi => ext}/CalendarData_hi.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hr => ext}/CalendarData_hr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hu => ext}/CalendarData_hu.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{in/ID => ext}/CalendarData_in_ID.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{is => ext}/CalendarData_is.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{it => ext}/CalendarData_it.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{iw => ext}/CalendarData_iw.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ja => ext}/CalendarData_ja.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ko => ext}/CalendarData_ko.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{lt => ext}/CalendarData_lt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{lv => ext}/CalendarData_lv.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mk => ext}/CalendarData_mk.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ms/MY => ext}/CalendarData_ms_MY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mt => ext}/CalendarData_mt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mt/MT => ext}/CalendarData_mt_MT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{nl => ext}/CalendarData_nl.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{no => ext}/CalendarData_no.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pl => ext}/CalendarData_pl.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt => ext}/CalendarData_pt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/BR => ext}/CalendarData_pt_BR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/PT => ext}/CalendarData_pt_PT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ro => ext}/CalendarData_ro.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ru => ext}/CalendarData_ru.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sk => ext}/CalendarData_sk.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sl => ext}/CalendarData_sl.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sq => ext}/CalendarData_sq.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr => ext}/CalendarData_sr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/BA => ext}/CalendarData_sr_Latn_BA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/ME => ext}/CalendarData_sr_Latn_ME.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/RS => ext}/CalendarData_sr_Latn_RS.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sv => ext}/CalendarData_sv.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{th => ext}/CalendarData_th.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{tr => ext}/CalendarData_tr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{uk => ext}/CalendarData_uk.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{vi => ext}/CalendarData_vi.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh => ext}/CalendarData_zh.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/AE => ext}/CurrencyNames_ar_AE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/BH => ext}/CurrencyNames_ar_BH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/DZ => ext}/CurrencyNames_ar_DZ.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/EG => ext}/CurrencyNames_ar_EG.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/IQ => ext}/CurrencyNames_ar_IQ.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/JO => ext}/CurrencyNames_ar_JO.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/KW => ext}/CurrencyNames_ar_KW.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/LB => ext}/CurrencyNames_ar_LB.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/LY => ext}/CurrencyNames_ar_LY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/MA => ext}/CurrencyNames_ar_MA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/OM => ext}/CurrencyNames_ar_OM.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/QA => ext}/CurrencyNames_ar_QA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/SA => ext}/CurrencyNames_ar_SA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/SD => ext}/CurrencyNames_ar_SD.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/SY => ext}/CurrencyNames_ar_SY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/TN => ext}/CurrencyNames_ar_TN.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar/YE => ext}/CurrencyNames_ar_YE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{be/BY => ext}/CurrencyNames_be_BY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{bg/BG => ext}/CurrencyNames_bg_BG.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ca/ES => ext}/CurrencyNames_ca_ES.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{cs/CZ => ext}/CurrencyNames_cs_CZ.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{da/DK => ext}/CurrencyNames_da_DK.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de => ext}/CurrencyNames_de.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de/AT => ext}/CurrencyNames_de_AT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de/CH => ext}/CurrencyNames_de_CH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de/DE => ext}/CurrencyNames_de_DE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de/GR => ext}/CurrencyNames_de_GR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de/LU => ext}/CurrencyNames_de_LU.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{el/CY => ext}/CurrencyNames_el_CY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{el/GR => ext}/CurrencyNames_el_GR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/AU => ext}/CurrencyNames_en_AU.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/CA => ext}/CurrencyNames_en_CA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/GB => ext}/CurrencyNames_en_GB.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/IE => ext}/CurrencyNames_en_IE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/IN => ext}/CurrencyNames_en_IN.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/MT => ext}/CurrencyNames_en_MT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/NZ => ext}/CurrencyNames_en_NZ.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/PH => ext}/CurrencyNames_en_PH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/SG => ext}/CurrencyNames_en_SG.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/ZA => ext}/CurrencyNames_en_ZA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es => ext}/CurrencyNames_es.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/AR => ext}/CurrencyNames_es_AR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/BO => ext}/CurrencyNames_es_BO.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/CL => ext}/CurrencyNames_es_CL.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/CO => ext}/CurrencyNames_es_CO.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/CR => ext}/CurrencyNames_es_CR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/CU => ext}/CurrencyNames_es_CU.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/DO => ext}/CurrencyNames_es_DO.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/EC => ext}/CurrencyNames_es_EC.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/ES => ext}/CurrencyNames_es_ES.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/GT => ext}/CurrencyNames_es_GT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/HN => ext}/CurrencyNames_es_HN.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/MX => ext}/CurrencyNames_es_MX.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/NI => ext}/CurrencyNames_es_NI.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/PA => ext}/CurrencyNames_es_PA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/PE => ext}/CurrencyNames_es_PE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/PR => ext}/CurrencyNames_es_PR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/PY => ext}/CurrencyNames_es_PY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/SV => ext}/CurrencyNames_es_SV.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/US => ext}/CurrencyNames_es_US.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/UY => ext}/CurrencyNames_es_UY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/VE => ext}/CurrencyNames_es_VE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{et/EE => ext}/CurrencyNames_et_EE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fi/FI => ext}/CurrencyNames_fi_FI.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr => ext}/CurrencyNames_fr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr/BE => ext}/CurrencyNames_fr_BE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr/CA => ext}/CurrencyNames_fr_CA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr/CH => ext}/CurrencyNames_fr_CH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr/FR => ext}/CurrencyNames_fr_FR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr/LU => ext}/CurrencyNames_fr_LU.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ga/IE => ext}/CurrencyNames_ga_IE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hi/IN => ext}/CurrencyNames_hi_IN.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hr/HR => ext}/CurrencyNames_hr_HR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hu/HU => ext}/CurrencyNames_hu_HU.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{in/ID => ext}/CurrencyNames_in_ID.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{is/IS => ext}/CurrencyNames_is_IS.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{it => ext}/CurrencyNames_it.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{it/CH => ext}/CurrencyNames_it_CH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{it/IT => ext}/CurrencyNames_it_IT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{iw/IL => ext}/CurrencyNames_iw_IL.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ja => ext}/CurrencyNames_ja.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ja/JP => ext}/CurrencyNames_ja_JP.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ko => ext}/CurrencyNames_ko.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ko/KR => ext}/CurrencyNames_ko_KR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{lt/LT => ext}/CurrencyNames_lt_LT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{lv/LV => ext}/CurrencyNames_lv_LV.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mk/MK => ext}/CurrencyNames_mk_MK.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ms/MY => ext}/CurrencyNames_ms_MY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mt/MT => ext}/CurrencyNames_mt_MT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{nl/BE => ext}/CurrencyNames_nl_BE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{nl/NL => ext}/CurrencyNames_nl_NL.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{no/NO => ext}/CurrencyNames_no_NO.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pl/PL => ext}/CurrencyNames_pl_PL.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt => ext}/CurrencyNames_pt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/BR => ext}/CurrencyNames_pt_BR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/PT => ext}/CurrencyNames_pt_PT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ro/RO => ext}/CurrencyNames_ro_RO.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ru/RU => ext}/CurrencyNames_ru_RU.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sk/SK => ext}/CurrencyNames_sk_SK.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sl/SI => ext}/CurrencyNames_sl_SI.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sq/AL => ext}/CurrencyNames_sq_AL.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/BA => ext}/CurrencyNames_sr_BA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/CS => ext}/CurrencyNames_sr_CS.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/BA => ext}/CurrencyNames_sr_Latn_BA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/ME => ext}/CurrencyNames_sr_Latn_ME.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/RS => ext}/CurrencyNames_sr_Latn_RS.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/ME => ext}/CurrencyNames_sr_ME.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr/RS => ext}/CurrencyNames_sr_RS.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sv => ext}/CurrencyNames_sv.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sv/SE => ext}/CurrencyNames_sv_SE.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{th/TH => ext}/CurrencyNames_th_TH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{tr/TR => ext}/CurrencyNames_tr_TR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{uk/UA => ext}/CurrencyNames_uk_UA.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{vi/VN => ext}/CurrencyNames_vi_VN.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/CN => ext}/CurrencyNames_zh_CN.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/HK => ext}/CurrencyNames_zh_HK.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/SG => ext}/CurrencyNames_zh_SG.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/TW => ext}/CurrencyNames_zh_TW.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ar => ext}/LocaleNames_ar.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{be => ext}/LocaleNames_be.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{bg => ext}/LocaleNames_bg.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ca => ext}/LocaleNames_ca.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{cs => ext}/LocaleNames_cs.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{da => ext}/LocaleNames_da.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de => ext}/LocaleNames_de.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{el => ext}/LocaleNames_el.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{el/CY => ext}/LocaleNames_el_CY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/MT => ext}/LocaleNames_en_MT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/PH => ext}/LocaleNames_en_PH.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/SG => ext}/LocaleNames_en_SG.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es => ext}/LocaleNames_es.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es/US => ext}/LocaleNames_es_US.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{et => ext}/LocaleNames_et.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fi => ext}/LocaleNames_fi.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr => ext}/LocaleNames_fr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ga => ext}/LocaleNames_ga.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hi => ext}/LocaleNames_hi.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hr => ext}/LocaleNames_hr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hu => ext}/LocaleNames_hu.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{in => ext}/LocaleNames_in.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{is => ext}/LocaleNames_is.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{it => ext}/LocaleNames_it.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{iw => ext}/LocaleNames_iw.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ja => ext}/LocaleNames_ja.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ko => ext}/LocaleNames_ko.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{lt => ext}/LocaleNames_lt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{lv => ext}/LocaleNames_lv.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mk => ext}/LocaleNames_mk.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ms => ext}/LocaleNames_ms.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{mt => ext}/LocaleNames_mt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{nl => ext}/LocaleNames_nl.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{no => ext}/LocaleNames_no.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{no/NO => ext}/LocaleNames_no_NO_NY.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pl => ext}/LocaleNames_pl.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt => ext}/LocaleNames_pt.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/BR => ext}/LocaleNames_pt_BR.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/PT => ext}/LocaleNames_pt_PT.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ro => ext}/LocaleNames_ro.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ru => ext}/LocaleNames_ru.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sk => ext}/LocaleNames_sk.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sl => ext}/LocaleNames_sl.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sq => ext}/LocaleNames_sq.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr => ext}/LocaleNames_sr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sr => ext}/LocaleNames_sr_Latn.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sv => ext}/LocaleNames_sv.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{th => ext}/LocaleNames_th.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{tr => ext}/LocaleNames_tr.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{uk => ext}/LocaleNames_uk.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{vi => ext}/LocaleNames_vi.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh => ext}/LocaleNames_zh.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/HK => ext}/LocaleNames_zh_HK.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/SG => ext}/LocaleNames_zh_SG.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/TW => ext}/LocaleNames_zh_TW.properties (100%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{de => ext}/TimeZoneNames_de.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/CA => ext}/TimeZoneNames_en_CA.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/GB => ext}/TimeZoneNames_en_GB.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{en/IE => ext}/TimeZoneNames_en_IE.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{es => ext}/TimeZoneNames_es.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{fr => ext}/TimeZoneNames_fr.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{hi => ext}/TimeZoneNames_hi.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{it => ext}/TimeZoneNames_it.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ja => ext}/TimeZoneNames_ja.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{ko => ext}/TimeZoneNames_ko.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{pt/BR => ext}/TimeZoneNames_pt_BR.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{sv => ext}/TimeZoneNames_sv.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/CN => ext}/TimeZoneNames_zh_CN.java (99%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/HK => ext}/TimeZoneNames_zh_HK.java (98%) rename jdk/src/jdk.localedata/share/classes/sun/util/resources/{zh/TW => ext}/TimeZoneNames_zh_TW.java (99%) diff --git a/jdk/make/gendata/GendataBreakIterator.gmk b/jdk/make/gendata/GendataBreakIterator.gmk index b2827da2f0f..2ca835c23d3 100644 --- a/jdk/make/gendata/GendataBreakIterator.gmk +++ b/jdk/make/gendata/GendataBreakIterator.gmk @@ -1,4 +1,4 @@ -# + # Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -36,10 +36,11 @@ TEXT_SRCDIR := $(JDK_TOPDIR)/src/java.base/share/classes \ $(JDK_TOPDIR)/src/jdk.localedata/share/classes TEXT_PKG := sun/text/resources +TEXT_PKG_LD := $(TEXT_PKG)/ext TEXT_SOURCES := $(TEXT_PKG)/BreakIteratorRules.java \ $(TEXT_PKG)/BreakIteratorInfo.java \ - $(TEXT_PKG)/th/BreakIteratorRules_th.java \ - $(TEXT_PKG)/th/BreakIteratorInfo_th.java + $(TEXT_PKG_LD)/BreakIteratorRules_th.java \ + $(TEXT_PKG_LD)/BreakIteratorInfo_th.java # Generate BreakIteratorData BREAK_ITERATOR_CLASSES := $(BUILDTOOLS_OUTPUTDIR)/break_iterator_classes @@ -62,8 +63,8 @@ BIFILES := $(BASE_DATA_PKG_DIR)/CharacterBreakIteratorData \ $(BASE_DATA_PKG_DIR)/WordBreakIteratorData \ $(BASE_DATA_PKG_DIR)/LineBreakIteratorData \ $(BASE_DATA_PKG_DIR)/SentenceBreakIteratorData -BIFILES_TH := $(LD_DATA_PKG_DIR)/th/WordBreakIteratorData_th \ - $(LD_DATA_PKG_DIR)/th/LineBreakIteratorData_th +BIFILES_TH := $(LD_DATA_PKG_DIR)/WordBreakIteratorData_th \ + $(LD_DATA_PKG_DIR)/LineBreakIteratorData_th $(BIFILES): $(BASE_DATA_PKG_DIR)/_the.bifiles $(BASE_DATA_PKG_DIR)/_the.bifiles: JAVA_FLAGS += -Xbootclasspath/p:$(BREAK_ITERATOR_CLASSES) @@ -80,7 +81,6 @@ $(BIFILES_TH): $(LD_DATA_PKG_DIR)/_the.bifiles_th $(LD_DATA_PKG_DIR)/_the.bifiles_th: JAVA_FLAGS += -Xbootclasspath/p:$(BREAK_ITERATOR_CLASSES) $(LD_DATA_PKG_DIR)/_the.bifiles_th: $(BUILD_TOOLS) $(UNICODEDATA) $(BUILD_BREAKITERATOR) $(call LogInfo, Generating BreakIteratorData_th) - $(call MakeDir, $(@D)/th) $(RM) $(BIFILES_TH) $(TOOL_GENERATEBREAKITERATORDATA) \ -o $(@D) \ diff --git a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java index 28f7cc8ed46..f15834202b0 100644 --- a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -504,12 +504,22 @@ public class CLDRConverter { * Examine if the id includes the country (territory) code. If it does, it returns * the country code. * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it return "SG". - * For now, it does not return US M.49 code, e.g., '001', as those three digit numbers cannot + * It does NOT return UN M.49 code, e.g., '001', as those three digit numbers cannot * be translated into package names. */ static String getCountryCode(String id) { - String ctry = Locale.forLanguageTag(id.replaceAll("_", "-")).getCountry(); - return ctry.length() == 2 ? ctry : null; + String rgn = getRegionCode(id); + return rgn.length() == 2 ? rgn: null; + } + + /** + * Examine if the id includes the region code. If it does, it returns + * the region code. + * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it return "SG". + * It DOES return UN M.49 code, e.g., '001', as well as ISO 3166 two letter country codes. + */ + static String getRegionCode(String id) { + return Locale.forLanguageTag(id.replaceAll("_", "-")).getCountry(); } private static class KeyComparator implements Comparator { diff --git a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index 26857aa2157..c2f16e823cf 100644 --- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -72,24 +72,20 @@ class ResourceBundleGenerator implements BundleGenerator { public void generateBundle(String packageName, String baseName, String localeID, boolean useJava, Map map, BundleType type) throws IOException { String suffix = useJava ? ".java" : ".properties"; - String lang = CLDRConverter.getLanguageCode(localeID); - String ctry = CLDRConverter.getCountryCode(localeID); String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + packageName + File.separator + "resources" + File.separator + "cldr"; - if (lang.length() > 0) { - if (CLDRConverter.isBaseModule ^ isBaseLocale(localeID)) { - return; - } - dirName = dirName + File.separator + lang + - (ctry != null && ctry.length() > 0 ? File.separator + ctry : ""); - packageName = packageName + ".resources.cldr." + lang + - (ctry != null && ctry.length() > 0 ? "." + ctry : ""); - } else { - if (!CLDRConverter.isBaseModule) { - return; - } - packageName = packageName + ".resources.cldr"; + packageName = packageName + ".resources.cldr"; + + if (CLDRConverter.isBaseModule ^ isBaseLocale(localeID)) { + return; } + + // Assume that non-base resources go into jdk.localedata + if (!CLDRConverter.isBaseModule) { + dirName = dirName + File.separator + "ext"; + packageName = packageName + ".ext"; + } + File dir = new File(dirName); if (!dir.exists()) { dir.mkdirs(); @@ -338,7 +334,7 @@ class ResourceBundleGenerator implements BundleGenerator { Locale locale = LOCALE_BUILDER .clear() .setLanguage(CLDRConverter.getLanguageCode(localeID)) - .setRegion(CLDRConverter.getCountryCode(localeID)) + .setRegion(CLDRConverter.getRegionCode(localeID)) .build(); return CLDRConverter.BASE_LOCALES.contains(locale); } diff --git a/jdk/make/src/classes/build/tools/generatebreakiteratordata/BreakIteratorRBControl.java b/jdk/make/src/classes/build/tools/generatebreakiteratordata/BreakIteratorRBControl.java deleted file mode 100644 index 0b4bd96bf11..00000000000 --- a/jdk/make/src/classes/build/tools/generatebreakiteratordata/BreakIteratorRBControl.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package build.tools.generatebreakiteratordata; - -import java.util.Arrays; -import java.util.ResourceBundle; -import java.util.List; -import java.util.Locale; - -class BreakIteratorRBControl extends ResourceBundle.Control { - static final BreakIteratorRBControl INSTANCE = new BreakIteratorRBControl(); - - private static final String RESOURCES = ".resources."; - - private BreakIteratorRBControl() { - } - - @Override - public Locale getFallbackLocale(String baseName, Locale locale) { - // No fallback - return null; - } - - @Override - public List getCandidateLocales(String baseName, Locale locale) { - // No parents lookup - return Arrays.asList(locale); - } - - /** - * Changes baseName to its per-language package name and - * calls the super class implementation. - */ - @Override - public String toBundleName(String baseName, Locale locale) { - String newBaseName = baseName; - String lang = locale.getLanguage(); - if (lang.length() > 0) { - int index = baseName.indexOf(RESOURCES); - if (index > 0) { - index += RESOURCES.length(); - newBaseName = baseName.substring(0, index) + lang + "." - + baseName.substring(index); - } - } - return super.toBundleName(newBaseName, locale); - } -} diff --git a/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java b/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java index db87521ee1a..c22fa683c80 100644 --- a/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java +++ b/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java @@ -45,11 +45,6 @@ public class GenerateBreakIteratorData { */ private static String unicodeData = "UnicodeData.txt"; - /** - * Rules file - */ - private static String rules = "sun.text.resources.BreakIteratorRules"; - /** * Locale data */ @@ -78,14 +73,14 @@ public class GenerateBreakIteratorData { String[] classNames; ResourceBundle rules, info; - info = ResourceBundle.getBundle("sun.text.resources.BreakIteratorInfo", - new Locale(language, country, valiant), - BreakIteratorRBControl.INSTANCE); + String pkgName = "sun.text.resources" + (language.length() > 0 ? ".ext" : ""); + + info = ResourceBundle.getBundle(pkgName + ".BreakIteratorInfo", + new Locale(language, country, valiant)); classNames = info.getStringArray("BreakIteratorClasses"); - rules = ResourceBundle.getBundle("sun.text.resources.BreakIteratorRules", - new Locale(language, country, valiant), - BreakIteratorRBControl.INSTANCE); + rules = ResourceBundle.getBundle(pkgName + ".BreakIteratorRules", + new Locale(language, country, valiant)); if (info.containsKey("CharacterData")) { generateDataFile(info.getString("CharacterData"), diff --git a/jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en.java b/jdk/src/java.base/share/classes/sun/text/resources/FormatData_en.java similarity index 99% rename from jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en.java rename to jdk/src/java.base/share/classes/sun/text/resources/FormatData_en.java index 85ae55daf21..117cfab0a30 100644 --- a/jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en.java +++ b/jdk/src/java.base/share/classes/sun/text/resources/FormatData_en.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en; +package sun.text.resources; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/java.base/share/classes/sun/text/resources/en/US/FormatData_en_US.java b/jdk/src/java.base/share/classes/sun/text/resources/FormatData_en_US.java similarity index 98% rename from jdk/src/java.base/share/classes/sun/text/resources/en/US/FormatData_en_US.java rename to jdk/src/java.base/share/classes/sun/text/resources/FormatData_en_US.java index 20a60c1099a..cf25a1c26fc 100644 --- a/jdk/src/java.base/share/classes/sun/text/resources/en/US/FormatData_en_US.java +++ b/jdk/src/java.base/share/classes/sun/text/resources/FormatData_en_US.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.US; +package sun.text.resources; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/java.base/share/classes/sun/text/resources/en/JavaTimeSupplementary_en.java b/jdk/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary_en.java similarity index 99% rename from jdk/src/java.base/share/classes/sun/text/resources/en/JavaTimeSupplementary_en.java rename to jdk/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary_en.java index 13005685bf4..62e66074c86 100644 --- a/jdk/src/java.base/share/classes/sun/text/resources/en/JavaTimeSupplementary_en.java +++ b/jdk/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary_en.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en; +package sun.text.resources; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/java.base/share/classes/sun/util/resources/en/CalendarData_en.properties b/jdk/src/java.base/share/classes/sun/util/resources/CalendarData_en.properties similarity index 100% rename from jdk/src/java.base/share/classes/sun/util/resources/en/CalendarData_en.properties rename to jdk/src/java.base/share/classes/sun/util/resources/CalendarData_en.properties diff --git a/jdk/src/java.base/share/classes/sun/util/resources/en/US/CurrencyNames_en_US.properties b/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNames_en_US.properties similarity index 100% rename from jdk/src/java.base/share/classes/sun/util/resources/en/US/CurrencyNames_en_US.properties rename to jdk/src/java.base/share/classes/sun/util/resources/CurrencyNames_en_US.properties diff --git a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java index 867a62253e4..51fa7395b96 100644 --- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java +++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java @@ -251,19 +251,20 @@ public class LocaleData { private static final String DOTCLDR = ".cldr"; /** - * Changes baseName to its per-language/country package name and + * Changes baseName to its module dependent package name and * calls the super class implementation. For example, * if the baseName is "sun.text.resources.FormatData" and locale is ja_JP, - * the baseName is changed to "sun.text.resources.ja.JP.FormatData". If + * the baseName is changed to "sun.text.resources.ext.FormatData". If * baseName contains "cldr", such as "sun.text.resources.cldr.FormatData", - * the name is changed to "sun.text.resources.cldr.ja.JP.FormatData". + * the name is changed to "sun.text.resources.cldr.ext.FormatData". */ @Override public String toBundleName(String baseName, Locale locale) { String newBaseName = baseName; String lang = locale.getLanguage(); String ctry = locale.getCountry(); - if (lang.length() > 0) { + if (lang.length() > 0 && + (lang != "en" || (ctry.length() > 0 && ctry != "US"))) { if (baseName.startsWith(JRE.getUtilResourcesPackage()) || baseName.startsWith(JRE.getTextResourcesPackage())) { // Assume the lengths are the same. @@ -273,9 +274,8 @@ public class LocaleData { if (baseName.indexOf(DOTCLDR, index) > 0) { index += DOTCLDR.length(); } - ctry = (ctry.length() == 2) ? ("." + ctry) : ""; - newBaseName = baseName.substring(0, index + 1) + lang + ctry - + baseName.substring(index); + newBaseName = baseName.substring(0, index + 1) + "ext" + + baseName.substring(index); } } return super.toBundleName(newBaseName, locale); diff --git a/jdk/src/java.base/share/classes/sun/util/resources/en/LocaleNames_en.properties b/jdk/src/java.base/share/classes/sun/util/resources/LocaleNames_en.properties similarity index 100% rename from jdk/src/java.base/share/classes/sun/util/resources/en/LocaleNames_en.properties rename to jdk/src/java.base/share/classes/sun/util/resources/LocaleNames_en.properties diff --git a/jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en.java b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames_en.java similarity index 98% rename from jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en.java rename to jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames_en.java index c8c92ce1f34..cc2199b8e21 100644 --- a/jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en.java +++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames_en.java @@ -39,7 +39,7 @@ * */ -package sun.util.resources.en; +package sun.util.resources; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/BreakIteratorInfo_th.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorInfo_th.java similarity index 92% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/BreakIteratorInfo_th.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorInfo_th.java index 34f1a2ab5de..f36a9c29d0b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/BreakIteratorInfo_th.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorInfo_th.java @@ -42,7 +42,7 @@ * will not be liable for any third party claims against you. */ -package sun.text.resources.th; +package sun.text.resources.ext; import java.util.ListResourceBundle; @@ -61,12 +61,12 @@ public class BreakIteratorInfo_th extends ListResourceBundle { }, // Data filename for each break-iterator - {"WordData", "th/WordBreakIteratorData_th"}, - {"LineData", "th/LineBreakIteratorData_th"}, + {"WordData", "WordBreakIteratorData_th"}, + {"LineData", "LineBreakIteratorData_th"}, // Dictionary filename for each dictionary-based break-iterator - {"WordDictionary", "th/thai_dict"}, - {"LineDictionary", "th/thai_dict"}, + {"WordDictionary", "thai_dict"}, + {"LineDictionary", "thai_dict"}, }; } } diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/BreakIteratorRules_th.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorRules_th.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/BreakIteratorRules_th.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorRules_th.java index 5b7ac26d2d7..c521b6ad6f8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/BreakIteratorRules_th.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorRules_th.java @@ -36,7 +36,7 @@ * are used on runtime instead. */ -package sun.text.resources.th; +package sun.text.resources.ext; import java.util.ListResourceBundle; import java.util.MissingResourceException; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/CollationData_ar.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ar.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/CollationData_ar.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ar.java index bfa0df464ed..6ecb0abbf69 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/CollationData_ar.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ar.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ar; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/CollationData_be.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_be.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/be/CollationData_be.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_be.java index 9615b31577c..1418683dae3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/CollationData_be.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_be.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.be; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/CollationData_bg.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_bg.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/CollationData_bg.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_bg.java index ec974cac17b..fa5b7159a1d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/CollationData_bg.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_bg.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.bg; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/CollationData_ca.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ca.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/CollationData_ca.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ca.java index 5f95e49a72a..1280ecfc1b8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/CollationData_ca.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ca.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ca; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/CollationData_cs.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_cs.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/CollationData_cs.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_cs.java index 5da77313028..057ede39ec5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/CollationData_cs.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_cs.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.cs; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/CollationData_da.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_da.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/da/CollationData_da.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_da.java index a0d2b9c6cea..9d24de10a6d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/CollationData_da.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_da.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.da; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/CollationData_el.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_el.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/el/CollationData_el.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_el.java index f71367b15e9..76f8391c9df 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/CollationData_el.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_el.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.el; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CollationData_es.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_es.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CollationData_es.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_es.java index 49bfa21e94e..36c359ec255 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CollationData_es.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_es.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.es; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/CollationData_et.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_et.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/et/CollationData_et.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_et.java index 092d12b8060..eecad8e724b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/CollationData_et.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_et.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.et; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/CollationData_fi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_fi.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/CollationData_fi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_fi.java index 0922b70a5ca..aec59942401 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/CollationData_fi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_fi.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.fi; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CollationData_fr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_fr.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CollationData_fr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_fr.java index 04b4cdaed5f..31a2b8e8fd3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CollationData_fr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_fr.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.fr; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/CollationData_hi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hi.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/CollationData_hi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hi.java index 8d40da6489e..b549fe9101b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/CollationData_hi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hi.java @@ -32,7 +32,7 @@ * */ -package sun.text.resources.hi; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/CollationData_hr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hr.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/CollationData_hr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hr.java index ac2fcc9fad3..4f116e078cb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/CollationData_hr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hr.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.hr; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/CollationData_hu.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hu.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/CollationData_hu.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hu.java index 3d22be64a3e..40f410b10eb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/CollationData_hu.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_hu.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.hu; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/CollationData_is.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_is.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/is/CollationData_is.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_is.java index 56d57b820b3..3ef46ddeef1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/CollationData_is.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_is.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.is; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/CollationData_iw.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_iw.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/CollationData_iw.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_iw.java index 5977062a23b..25fea11ef1e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/CollationData_iw.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_iw.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.iw; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/CollationData_ja.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ja.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/CollationData_ja.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ja.java index e65e8f2febf..3866725644e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/CollationData_ja.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ja.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ja; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/CollationData_ko.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ko.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/CollationData_ko.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ko.java index ebeb8045735..b8e80ec4189 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/CollationData_ko.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ko.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ko; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/CollationData_lt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_lt.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/CollationData_lt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_lt.java index ac1885f0633..8c73da07b86 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/CollationData_lt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_lt.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.lt; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/CollationData_lv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_lv.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/CollationData_lv.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_lv.java index 55968ce32a4..3c0e618e08d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/CollationData_lv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_lv.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.lv; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/CollationData_mk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_mk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/CollationData_mk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_mk.java index 5d6ed9421c1..a721209456d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/CollationData_mk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_mk.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.mk; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/CollationData_no.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_no.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/no/CollationData_no.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_no.java index 6a03b0dff24..806dfa07a1f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/CollationData_no.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_no.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.no; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/CollationData_pl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_pl.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/CollationData_pl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_pl.java index 4bbf24ab424..d542d04e374 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/CollationData_pl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_pl.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.pl; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/CollationData_ro.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ro.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/CollationData_ro.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ro.java index 37f8738a715..dffc3a1a97a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/CollationData_ro.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ro.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ro; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/CollationData_ru.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ru.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/CollationData_ru.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ru.java index 79ec2db6dc1..3ebd0b8d7f5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/CollationData_ru.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_ru.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ru; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/CollationData_sk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sk.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/CollationData_sk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sk.java index b75fd3bec26..82560dfbb19 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/CollationData_sk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sk.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.sk; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/CollationData_sl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sl.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/CollationData_sl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sl.java index d1f7dab47f5..c24d69e5a02 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/CollationData_sl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sl.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.sl; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/CollationData_sq.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sq.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/CollationData_sq.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sq.java index 2c88d692ecb..830a0ac43e6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/CollationData_sq.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sq.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.sq; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CollationData_sr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CollationData_sr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sr.java index 25583a25765..5c4b287ae94 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CollationData_sr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sr.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.sr; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CollationData_sr_Latn.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sr_Latn.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CollationData_sr_Latn.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sr_Latn.java index 633b52c8e4d..18082d0d582 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CollationData_sr_Latn.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sr_Latn.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.sr; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/CollationData_sv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sv.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/CollationData_sv.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sv.java index 6b281101e33..e633c572ed8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/CollationData_sv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_sv.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.sv; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/CollationData_th.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_th.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/CollationData_th.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_th.java index ffb950b57c5..1a8a49d841f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/CollationData_th.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_th.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.th; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/CollationData_tr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_tr.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/CollationData_tr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_tr.java index fbfda4b9d21..bfd6a1a7b38 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/CollationData_tr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_tr.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.tr; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/CollationData_uk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_uk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/CollationData_uk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_uk.java index d0d76ff3998..2cd687f8854 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/CollationData_uk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_uk.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.uk; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/CollationData_vi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_vi.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/CollationData_vi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_vi.java index 49eccdfba02..68390d65eea 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/CollationData_vi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_vi.java @@ -43,7 +43,7 @@ * http://oss.software.ibm.com/cvs/icu/icu/source/data/locales/vi.txt?rev=1.38 */ -package sun.text.resources.vi; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/CollationData_zh.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/CollationData_zh.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh.java index 14ed1a9d4c5..51dfbb20676 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/CollationData_zh.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.zh; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/HK/CollationData_zh_HK.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh_HK.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/HK/CollationData_zh_HK.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh_HK.java index 08849990126..b7fd5af7d4e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/HK/CollationData_zh_HK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh_HK.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.zh.HK; +package sun.text.resources.ext; import java.util.ListResourceBundle; import java.util.Locale; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/CollationData_zh_TW.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh_TW.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/CollationData_zh_TW.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh_TW.java index bfa4a9a7709..85e36381ba6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/CollationData_zh_TW.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/CollationData_zh_TW.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.zh.TW; +package sun.text.resources.ext; import java.util.ListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/FormatData_ar.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/FormatData_ar.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar.java index 3be4cd39e6f..5290a8ea76f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/FormatData_ar.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.ar; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JO/FormatData_ar_JO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_JO.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JO/FormatData_ar_JO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_JO.java index 572183f70eb..81211d18cfa 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JO/FormatData_ar_JO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_JO.java @@ -40,7 +40,7 @@ * */ -package sun.text.resources.ar.JO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/LB/FormatData_ar_LB.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_LB.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/LB/FormatData_ar_LB.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_LB.java index 71ad17ec91f..48e2dbcddd4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/LB/FormatData_ar_LB.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_LB.java @@ -40,7 +40,7 @@ * */ -package sun.text.resources.ar.LB; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/SY/FormatData_ar_SY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_SY.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/SY/FormatData_ar_SY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_SY.java index da6532d03aa..5f8bbca8a24 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/SY/FormatData_ar_SY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ar_SY.java @@ -40,7 +40,7 @@ * */ -package sun.text.resources.ar.SY; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/FormatData_be.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_be.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/be/FormatData_be.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_be.java index bed17d2f4f1..98e5ebfe21f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/FormatData_be.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_be.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.be; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/BY/FormatData_be_BY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_be_BY.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/be/BY/FormatData_be_BY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_be_BY.java index 0d5f8f697e4..c19b961c463 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/BY/FormatData_be_BY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_be_BY.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.be.BY; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/FormatData_bg.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_bg.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/FormatData_bg.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_bg.java index b97e2746277..693bf6a9a5e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/FormatData_bg.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_bg.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.bg; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/BG/FormatData_bg_BG.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_bg_BG.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/BG/FormatData_bg_BG.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_bg_BG.java index b7647002b1c..6a26bf48e95 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/BG/FormatData_bg_BG.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_bg_BG.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.bg.BG; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/FormatData_ca.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ca.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/FormatData_ca.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ca.java index 153b907e377..ef7eafb8fa5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/FormatData_ca.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ca.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.ca; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/ES/FormatData_ca_ES.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ca_ES.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/ES/FormatData_ca_ES.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ca_ES.java index 7d20e377603..5a96828d412 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/ES/FormatData_ca_ES.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ca_ES.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.ca.ES; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/FormatData_cs.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_cs.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/FormatData_cs.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_cs.java index 19ab68d18cd..2f68a4b5ec8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/FormatData_cs.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_cs.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.cs; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/CZ/FormatData_cs_CZ.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_cs_CZ.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/CZ/FormatData_cs_CZ.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_cs_CZ.java index d7643ef8793..38a4929a6ff 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/CZ/FormatData_cs_CZ.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_cs_CZ.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.cs.CZ; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/FormatData_da.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_da.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/da/FormatData_da.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_da.java index 13efb6f3df9..875c13231c0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/FormatData_da.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_da.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.da; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/DK/FormatData_da_DK.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_da_DK.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/da/DK/FormatData_da_DK.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_da_DK.java index 2987353d6db..d8586733eb5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/DK/FormatData_da_DK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_da_DK.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.da.DK; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de.java index 85c079cbb32..44c41fd6652 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/FormatData_de.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.de; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/AT/FormatData_de_AT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_AT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/AT/FormatData_de_AT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_AT.java index 8e264ed7704..cfeeb331813 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/AT/FormatData_de_AT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_AT.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.de.AT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/CH/FormatData_de_CH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_CH.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/CH/FormatData_de_CH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_CH.java index edb6b9ddb5e..d6cdb878281 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/CH/FormatData_de_CH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_CH.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.de.CH; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/DE/FormatData_de_DE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_DE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/DE/FormatData_de_DE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_DE.java index b32c8cd2973..b98fa44b7e8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/DE/FormatData_de_DE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_DE.java @@ -41,7 +41,7 @@ * */ -package sun.text.resources.de.DE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/LU/FormatData_de_LU.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_LU.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/LU/FormatData_de_LU.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_LU.java index 00dfe88fc4b..3227d89abd0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/LU/FormatData_de_LU.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_de_LU.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.de.LU; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/FormatData_el.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/el/FormatData_el.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el.java index 430d0e99a19..0141b644cfb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/FormatData_el.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el.java @@ -77,7 +77,7 @@ * of the copyright holder. */ -package sun.text.resources.el; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/CY/FormatData_el_CY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el_CY.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/el/CY/FormatData_el_CY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el_CY.java index bcdddaaa60f..9e50ed3ea01 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/CY/FormatData_el_CY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el_CY.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.el.CY; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/GR/FormatData_el_GR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el_GR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/el/GR/FormatData_el_GR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el_GR.java index f43e5b81a11..d4038b59a69 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/GR/FormatData_el_GR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_el_GR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.el.GR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/AU/FormatData_en_AU.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_AU.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/AU/FormatData_en_AU.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_AU.java index e9253fd7078..6ca4c7f329f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/AU/FormatData_en_AU.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_AU.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.AU; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/CA/FormatData_en_CA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_CA.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/CA/FormatData_en_CA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_CA.java index a0980c16816..b6c34fe2d36 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/CA/FormatData_en_CA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_CA.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.CA; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/GB/FormatData_en_GB.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_GB.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/GB/FormatData_en_GB.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_GB.java index de39a6633ca..e1f70e95fc9 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/GB/FormatData_en_GB.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_GB.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.GB; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IE/FormatData_en_IE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_IE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IE/FormatData_en_IE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_IE.java index 5793e00985f..c5f06379836 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IE/FormatData_en_IE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_IE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.IE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IN/FormatData_en_IN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_IN.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IN/FormatData_en_IN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_IN.java index 037cc2cd5a4..ed5f5cedadf 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IN/FormatData_en_IN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_IN.java @@ -29,7 +29,7 @@ * */ -package sun.text.resources.en.IN; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/MT/FormatData_en_MT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_MT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/MT/FormatData_en_MT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_MT.java index 16241deda00..9724bbae825 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/MT/FormatData_en_MT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_MT.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.en.MT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/NZ/FormatData_en_NZ.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_NZ.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/NZ/FormatData_en_NZ.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_NZ.java index 1970281bc0b..4645225afa2 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/NZ/FormatData_en_NZ.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_NZ.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.NZ; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/PH/FormatData_en_PH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_PH.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/PH/FormatData_en_PH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_PH.java index a4c740a422f..193ae6bf98d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/PH/FormatData_en_PH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_PH.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.en.PH; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/SG/FormatData_en_SG.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_SG.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/SG/FormatData_en_SG.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_SG.java index 5f5438bfb28..53cab53e273 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/SG/FormatData_en_SG.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_SG.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.en.SG; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/ZA/FormatData_en_ZA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_ZA.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/ZA/FormatData_en_ZA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_ZA.java index 9325ff63888..1e547e16aa9 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/ZA/FormatData_en_ZA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_en_ZA.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.en.ZA; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/FormatData_es.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/FormatData_es.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es.java index abb1607282b..f927a5805ba 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/FormatData_es.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.es; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/AR/FormatData_es_AR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_AR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/AR/FormatData_es_AR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_AR.java index 796826b2bcd..03018309b7f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/AR/FormatData_es_AR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_AR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.AR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/BO/FormatData_es_BO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_BO.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/BO/FormatData_es_BO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_BO.java index 11488326bd1..859868e54d4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/BO/FormatData_es_BO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_BO.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.BO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CL/FormatData_es_CL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CL.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CL/FormatData_es_CL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CL.java index 2c23f46197c..8015cd970ab 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CL/FormatData_es_CL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CL.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.CL; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CO/FormatData_es_CO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CO.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CO/FormatData_es_CO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CO.java index 2da0ece1bd3..0af9bd9165d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CO/FormatData_es_CO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CO.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.CO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CR/FormatData_es_CR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CR.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CR/FormatData_es_CR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CR.java index c47a8e39b08..30e94e11841 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CR/FormatData_es_CR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_CR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.CR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/DO/FormatData_es_DO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_DO.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/DO/FormatData_es_DO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_DO.java index b552b6e40c4..08d0a570b5b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/DO/FormatData_es_DO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_DO.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.DO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/EC/FormatData_es_EC.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_EC.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/EC/FormatData_es_EC.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_EC.java index 84c7c1ad7eb..877c1160c96 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/EC/FormatData_es_EC.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_EC.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.EC; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/ES/FormatData_es_ES.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_ES.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/ES/FormatData_es_ES.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_ES.java index 9ec97ee305f..8d8a986a96e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/ES/FormatData_es_ES.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_ES.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.ES; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/GT/FormatData_es_GT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_GT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/GT/FormatData_es_GT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_GT.java index 1639621c0f3..f50561972be 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/GT/FormatData_es_GT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_GT.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.GT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/HN/FormatData_es_HN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_HN.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/HN/FormatData_es_HN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_HN.java index 1d3feae8297..b9281045f98 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/HN/FormatData_es_HN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_HN.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.HN; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/MX/FormatData_es_MX.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_MX.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/MX/FormatData_es_MX.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_MX.java index a18e5ab3185..f943cfa01be 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/MX/FormatData_es_MX.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_MX.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.MX; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/NI/FormatData_es_NI.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_NI.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/NI/FormatData_es_NI.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_NI.java index caaea494bc8..260f2dec798 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/NI/FormatData_es_NI.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_NI.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.NI; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PA/FormatData_es_PA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PA.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PA/FormatData_es_PA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PA.java index d4d3159614f..49d3a197804 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PA/FormatData_es_PA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PA.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.PA; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PE/FormatData_es_PE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PE/FormatData_es_PE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PE.java index 6bf20025c75..5d483d6f75d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PE/FormatData_es_PE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.PE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PR/FormatData_es_PR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PR.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PR/FormatData_es_PR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PR.java index 1161173808b..09cb4e6236b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PR/FormatData_es_PR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.PR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PY/FormatData_es_PY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PY.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PY/FormatData_es_PY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PY.java index e89eb1ef3e7..c22260cffb1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PY/FormatData_es_PY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_PY.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.PY; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/SV/FormatData_es_SV.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_SV.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/SV/FormatData_es_SV.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_SV.java index cfca46e6ac4..2d1a51f3441 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/SV/FormatData_es_SV.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_SV.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.SV; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/US/FormatData_es_US.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_US.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/US/FormatData_es_US.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_US.java index 0fda4ae82f9..2b6f499099c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/US/FormatData_es_US.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_US.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.es.US; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/UY/FormatData_es_UY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_UY.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/UY/FormatData_es_UY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_UY.java index f99c1bdf5e3..49cdac330cb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/UY/FormatData_es_UY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_UY.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.UY; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/VE/FormatData_es_VE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_VE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/VE/FormatData_es_VE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_VE.java index ac613d95939..571412e5954 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/VE/FormatData_es_VE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_es_VE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.es.VE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/FormatData_et.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_et.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/et/FormatData_et.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_et.java index b7f70d02377..a9168a4ba28 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/FormatData_et.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_et.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.et; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/EE/FormatData_et_EE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_et_EE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/et/EE/FormatData_et_EE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_et_EE.java index 34914483ad4..26881b589b3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/EE/FormatData_et_EE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_et_EE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.et.EE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/FormatData_fi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fi.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/FormatData_fi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fi.java index c9a520a8388..9ecc89a9c27 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/FormatData_fi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fi.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.fi; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/FI/FormatData_fi_FI.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fi_FI.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/FI/FormatData_fi_FI.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fi_FI.java index ec6195e81a9..cc16dc872a1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/FI/FormatData_fi_FI.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fi_FI.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.fi.FI; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/FormatData_fr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/FormatData_fr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr.java index 7feee171002..662d5afde94 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/FormatData_fr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.fr; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/BE/FormatData_fr_BE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_BE.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/BE/FormatData_fr_BE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_BE.java index 424de742a75..88335059dfc 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/BE/FormatData_fr_BE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_BE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.fr.BE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CA/FormatData_fr_CA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_CA.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CA/FormatData_fr_CA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_CA.java index 10e3b572dd9..7f215423ab7 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CA/FormatData_fr_CA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_CA.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.fr.CA; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CH/FormatData_fr_CH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_CH.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CH/FormatData_fr_CH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_CH.java index 7da265871bd..6206b7ad53d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CH/FormatData_fr_CH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_CH.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.fr.CH; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/FR/FormatData_fr_FR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_FR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/FR/FormatData_fr_FR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_FR.java index 7b6704eba52..a10b431d5cb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/FR/FormatData_fr_FR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_fr_FR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.fr.FR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/FormatData_ga.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ga.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/FormatData_ga.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ga.java index fea8a7d1e1b..717a6f6ffe6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/FormatData_ga.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ga.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.ga; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/IE/FormatData_ga_IE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ga_IE.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/IE/FormatData_ga_IE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ga_IE.java index 8c8bb9f2389..86870e44008 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/IE/FormatData_ga_IE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ga_IE.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.ga.IE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/IN/FormatData_hi_IN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hi_IN.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/IN/FormatData_hi_IN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hi_IN.java index db5a9c165fc..69e3369b289 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/IN/FormatData_hi_IN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hi_IN.java @@ -65,7 +65,7 @@ * of the copyright holder. */ -package sun.text.resources.hi.IN; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/FormatData_hr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/FormatData_hr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hr.java index cd50304a62f..2446a856edd 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/FormatData_hr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hr.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.hr; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/HR/FormatData_hr_HR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hr_HR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/HR/FormatData_hr_HR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hr_HR.java index 09c1aa25006..25bfbc3aea1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/HR/FormatData_hr_HR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hr_HR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.hr.HR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/FormatData_hu.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hu.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/FormatData_hu.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hu.java index d5e53685114..5ca61a9d081 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/FormatData_hu.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hu.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.hu; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/HU/FormatData_hu_HU.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hu_HU.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/HU/FormatData_hu_HU.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hu_HU.java index a3fdc49d25d..4ef26559c6d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/HU/FormatData_hu_HU.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_hu_HU.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.hu.HU; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/in/FormatData_in.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_in.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/in/FormatData_in.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_in.java index 4eb35408d76..9b75e8ca1fc 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/in/FormatData_in.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_in.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.in; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/in/ID/FormatData_in_ID.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_in_ID.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/in/ID/FormatData_in_ID.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_in_ID.java index fda82717ee4..d9b14c201f8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/in/ID/FormatData_in_ID.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_in_ID.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.in.ID; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/FormatData_is.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_is.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/is/FormatData_is.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_is.java index ffb2cb0bb47..d381c6b621e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/FormatData_is.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_is.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.is; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/IS/FormatData_is_IS.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_is_IS.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/is/IS/FormatData_is_IS.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_is_IS.java index 50615b76114..1410c13ac31 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/IS/FormatData_is_IS.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_is_IS.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.is.IS; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/FormatData_it.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/it/FormatData_it.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it.java index 4c75a09bed6..d765f3e9ec4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/FormatData_it.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.it; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/CH/FormatData_it_CH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it_CH.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/it/CH/FormatData_it_CH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it_CH.java index e1d005b9bd1..2962e07d1a4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/CH/FormatData_it_CH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it_CH.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.it.CH; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/IT/FormatData_it_IT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it_IT.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/it/IT/FormatData_it_IT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it_IT.java index 3b4ebb3fd1a..cf206442197 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/IT/FormatData_it_IT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_it_IT.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.it.IT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/FormatData_iw.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_iw.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/FormatData_iw.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_iw.java index 4e52da31e05..93441b49dfa 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/FormatData_iw.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_iw.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.iw; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/IL/FormatData_iw_IL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_iw_IL.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/IL/FormatData_iw_IL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_iw_IL.java index 5d331187399..8fefe693a77 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/IL/FormatData_iw_IL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_iw_IL.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.iw.IL; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/FormatData_ja.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/FormatData_ja.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java index 591cd35cb49..b88cf85502a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/FormatData_ja.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.ja; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/JP/FormatData_ja_JP.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja_JP.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/JP/FormatData_ja_JP.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja_JP.java index fed18ed5a82..291fc038cf6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/JP/FormatData_ja_JP.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja_JP.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.ja.JP; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/FormatData_ko.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ko.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/FormatData_ko.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ko.java index 4483ad2e948..045a3b2b307 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/FormatData_ko.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ko.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.ko; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/KR/FormatData_ko_KR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ko_KR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/KR/FormatData_ko_KR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ko_KR.java index a7f7b108b17..4cfb78e7b52 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/KR/FormatData_ko_KR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ko_KR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.ko.KR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/FormatData_lt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lt.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/FormatData_lt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lt.java index 20a61db41e3..954689b58b6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/FormatData_lt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lt.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.lt; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/LT/FormatData_lt_LT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lt_LT.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/LT/FormatData_lt_LT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lt_LT.java index c0004056cef..128c46300f1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/LT/FormatData_lt_LT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lt_LT.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.lt.LT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/FormatData_lv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lv.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/FormatData_lv.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lv.java index fbba0219f58..da06b0e94a5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/FormatData_lv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lv.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.lv; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/LV/FormatData_lv_LV.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lv_LV.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/LV/FormatData_lv_LV.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lv_LV.java index e6c81ca5804..9db535ec8b4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/LV/FormatData_lv_LV.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_lv_LV.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.lv.LV; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/FormatData_mk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/FormatData_mk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mk.java index cb2d06df46c..34bd4d19c71 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/FormatData_mk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mk.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.mk; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/MK/FormatData_mk_MK.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mk_MK.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/MK/FormatData_mk_MK.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mk_MK.java index db567cdfe46..481eaea1e45 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/MK/FormatData_mk_MK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mk_MK.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.mk.MK; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/FormatData_ms.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ms.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/FormatData_ms.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ms.java index 4470069d9c6..c66b2c2340b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/FormatData_ms.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ms.java @@ -38,7 +38,7 @@ * of the copyright holder. */ -package sun.text.resources.ms; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/MY/FormatData_ms_MY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ms_MY.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/MY/FormatData_ms_MY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ms_MY.java index e4563d271b9..c6bf88a45cf 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/MY/FormatData_ms_MY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ms_MY.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.ms.MY; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/FormatData_mt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mt.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/FormatData_mt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mt.java index 12f266c5a26..20b1efa207d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/FormatData_mt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mt.java @@ -38,7 +38,7 @@ * of the copyright holder. */ -package sun.text.resources.mt; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/MT/FormatData_mt_MT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mt_MT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/MT/FormatData_mt_MT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mt_MT.java index 6a218d768db..cbbd356235a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/MT/FormatData_mt_MT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_mt_MT.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.mt.MT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/FormatData_nl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/FormatData_nl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl.java index 461e40fbb5a..f433220c994 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/FormatData_nl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.nl; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/BE/FormatData_nl_BE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl_BE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/BE/FormatData_nl_BE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl_BE.java index e4c811c4973..191619a4005 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/BE/FormatData_nl_BE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl_BE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.nl.BE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/NL/FormatData_nl_NL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl_NL.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/NL/FormatData_nl_NL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl_NL.java index e1301dc2375..ecfa1f5ee95 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/NL/FormatData_nl_NL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_nl_NL.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.nl.NL; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/FormatData_no.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/no/FormatData_no.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no.java index 3e24ebc515e..0f99dd39fb5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/FormatData_no.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.no; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/NO/FormatData_no_NO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no_NO.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/no/NO/FormatData_no_NO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no_NO.java index a1b93a722f8..f182cfac339 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/NO/FormatData_no_NO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no_NO.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.no.NO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/NO/FormatData_no_NO_NY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no_NO_NY.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/no/NO/FormatData_no_NO_NY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no_NO_NY.java index 707253107fa..c14c28a447b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/NO/FormatData_no_NO_NY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_no_NO_NY.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.no.NO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/FormatData_pl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pl.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/FormatData_pl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pl.java index 0df28fd4850..75c0ced1618 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/FormatData_pl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pl.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.pl; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/PL/FormatData_pl_PL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pl_PL.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/PL/FormatData_pl_PL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pl_PL.java index 479a363ebab..8b06f7d7919 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/PL/FormatData_pl_PL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pl_PL.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.pl.PL; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/FormatData_pt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/FormatData_pt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt.java index 32e6c1e14b2..e086106edf0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/FormatData_pt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.pt; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/BR/FormatData_pt_BR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt_BR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/BR/FormatData_pt_BR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt_BR.java index 8c85c03d528..e1d48eb7b70 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/BR/FormatData_pt_BR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt_BR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.pt.BR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/PT/FormatData_pt_PT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt_PT.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/PT/FormatData_pt_PT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt_PT.java index 267935b5b7a..6abd5140411 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/PT/FormatData_pt_PT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_pt_PT.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.pt.PT; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/FormatData_ro.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ro.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/FormatData_ro.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ro.java index b8dee7c5500..cab5053f93d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/FormatData_ro.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ro.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.ro; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/RO/FormatData_ro_RO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ro_RO.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/RO/FormatData_ro_RO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ro_RO.java index 9d30b6ba17a..51d9d11b5f6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/RO/FormatData_ro_RO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ro_RO.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.ro.RO; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/FormatData_ru.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ru.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/FormatData_ru.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ru.java index 90b7df279c2..620ce9b1db9 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/FormatData_ru.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ru.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.ru; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/RU/FormatData_ru_RU.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ru_RU.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/RU/FormatData_ru_RU.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ru_RU.java index ec88d5a8392..e1d26256d73 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/RU/FormatData_ru_RU.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ru_RU.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.ru.RU; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/FormatData_sk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/FormatData_sk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sk.java index b55517fbb68..37bd853dfcf 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/FormatData_sk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sk.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.sk; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/SK/FormatData_sk_SK.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sk_SK.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/SK/FormatData_sk_SK.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sk_SK.java index 68882392463..05b8cc0ccba 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/SK/FormatData_sk_SK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sk_SK.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.sk.SK; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/FormatData_sl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sl.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/FormatData_sl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sl.java index cdc2a596b62..d5f62f6c516 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/FormatData_sl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sl.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.sl; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/SI/FormatData_sl_SI.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sl_SI.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/SI/FormatData_sl_SI.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sl_SI.java index ae4af6e1b6a..fbfe1a95af0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/SI/FormatData_sl_SI.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sl_SI.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.sl.SI; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/FormatData_sq.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sq.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/FormatData_sq.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sq.java index a6edf3bd1e0..d00a8d9dab6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/FormatData_sq.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sq.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.sq; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/AL/FormatData_sq_AL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sq_AL.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/AL/FormatData_sq_AL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sq_AL.java index 061f5291051..09e9906df00 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/AL/FormatData_sq_AL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sq_AL.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.sq.AL; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/FormatData_sr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/FormatData_sr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr.java index 4d244073517..7faae421880 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/FormatData_sr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr.java @@ -38,7 +38,7 @@ * of the copyright holder. */ -package sun.text.resources.sr; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/BA/FormatData_sr_BA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_BA.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/BA/FormatData_sr_BA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_BA.java index e061831574c..e8c32bc069e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/BA/FormatData_sr_BA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_BA.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.sr.BA; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CS/FormatData_sr_CS.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_CS.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CS/FormatData_sr_CS.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_CS.java index 3a2bf651489..6965c028275 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/CS/FormatData_sr_CS.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_CS.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.sr.CS; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/FormatData_sr_Latn.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/FormatData_sr_Latn.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java index 198b911eae9..6c6a8d9e5dc 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/FormatData_sr_Latn.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java @@ -61,7 +61,7 @@ * written authorization of the copyright holder. */ -package sun.text.resources.sr; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/ME/FormatData_sr_Latn_ME.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn_ME.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/ME/FormatData_sr_Latn_ME.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn_ME.java index eee5e0fbfd5..c6ad77151c8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/ME/FormatData_sr_Latn_ME.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn_ME.java @@ -61,7 +61,7 @@ * written authorization of the copyright holder. */ -package sun.text.resources.sr.ME; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/ME/FormatData_sr_ME.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_ME.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/ME/FormatData_sr_ME.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_ME.java index f3abe6b5383..4d88af55115 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/ME/FormatData_sr_ME.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_ME.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.sr.ME; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/RS/FormatData_sr_RS.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_RS.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/RS/FormatData_sr_RS.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_RS.java index da0f5ab75cd..84a2fcbc479 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/RS/FormatData_sr_RS.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_RS.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.sr.RS; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/FormatData_sv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/FormatData_sv.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java index 8f7296bcee2..f22ca8ccb9a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/FormatData_sv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.sv; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/SE/FormatData_sv_SE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv_SE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/SE/FormatData_sv_SE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv_SE.java index a50cdfac40e..7e8e3522b84 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/SE/FormatData_sv_SE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv_SE.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.sv.SE; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/FormatData_th.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_th.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/FormatData_th.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_th.java index 15c679a0d98..617f26d902f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/FormatData_th.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_th.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.th; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/TH/FormatData_th_TH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_th_TH.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/TH/FormatData_th_TH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_th_TH.java index 627d49e37ce..48d041caa0e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/TH/FormatData_th_TH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_th_TH.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.th.TH; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/FormatData_tr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_tr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/FormatData_tr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_tr.java index 8f37c6058bd..585cc65e46e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/FormatData_tr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_tr.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.tr; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/TR/FormatData_tr_TR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_tr_TR.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/TR/FormatData_tr_TR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_tr_TR.java index 841fee1f580..babd8009ef1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/TR/FormatData_tr_TR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_tr_TR.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.tr.TR; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/FormatData_uk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_uk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/FormatData_uk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_uk.java index 6054f22fdf6..426df953fba 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/FormatData_uk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_uk.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.uk; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/UA/FormatData_uk_UA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_uk_UA.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/UA/FormatData_uk_UA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_uk_UA.java index d9a13f76c3b..a0af11ba007 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/UA/FormatData_uk_UA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_uk_UA.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.uk.UA; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/FormatData_vi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_vi.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/FormatData_vi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_vi.java index 55c5e3ebc75..58e62648ee5 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/FormatData_vi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_vi.java @@ -76,7 +76,7 @@ * of the copyright holder. */ -package sun.text.resources.vi; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/VN/FormatData_vi_VN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_vi_VN.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/VN/FormatData_vi_VN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_vi_VN.java index 8b71d47690c..4a7a2675c59 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/VN/FormatData_vi_VN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_vi_VN.java @@ -40,7 +40,7 @@ * http://oss.software.ibm.com/cvs/icu/icu/source/data/locales/vi.txt?rev=1.38 */ -package sun.text.resources.vi.VN; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/FormatData_zh.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/FormatData_zh.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java index 1f8f7cb31ff..491dd0cd2bf 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/FormatData_zh.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.zh; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/CN/FormatData_zh_CN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_CN.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/CN/FormatData_zh_CN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_CN.java index 195d52d6fc1..b0c6d88e8b4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/CN/FormatData_zh_CN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_CN.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.zh.CN; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/HK/FormatData_zh_HK.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_HK.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/HK/FormatData_zh_HK.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_HK.java index adfadc609dd..ea8665e1868 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/HK/FormatData_zh_HK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_HK.java @@ -38,7 +38,7 @@ * */ -package sun.text.resources.zh.HK; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; import java.util.Locale; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/SG/FormatData_zh_SG.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_SG.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/SG/FormatData_zh_SG.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_SG.java index 716c952a8c1..0decb3cd826 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/SG/FormatData_zh_SG.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_SG.java @@ -59,7 +59,7 @@ * authorization of the copyright holder. */ -package sun.text.resources.zh.SG; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/FormatData_zh_TW.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/FormatData_zh_TW.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java index 3bb2a807d7d..69003106237 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/FormatData_zh_TW.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java @@ -74,7 +74,7 @@ * of the copyright holder. */ -package sun.text.resources.zh.TW; +package sun.text.resources.ext; import sun.util.resources.ParallelListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar.java index 4e761f42ac6..9055855c5f3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ar; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JO/JavaTimeSupplementary_ar_JO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_JO.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JO/JavaTimeSupplementary_ar_JO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_JO.java index 8031a8cc3b8..3dfd781e626 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/JO/JavaTimeSupplementary_ar_JO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_JO.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ar.JO; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/LB/JavaTimeSupplementary_ar_LB.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_LB.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/LB/JavaTimeSupplementary_ar_LB.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_LB.java index 88a5f6c9faf..c0795d1f641 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/LB/JavaTimeSupplementary_ar_LB.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_LB.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ar.LB; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/SY/JavaTimeSupplementary_ar_SY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_SY.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/SY/JavaTimeSupplementary_ar_SY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_SY.java index cc413228eb9..6edcfe4089b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ar/SY/JavaTimeSupplementary_ar_SY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ar_SY.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ar.SY; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/JavaTimeSupplementary_be.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_be.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/be/JavaTimeSupplementary_be.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_be.java index 1c129d4a97e..e2dcb10ef2f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/be/JavaTimeSupplementary_be.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_be.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.be; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/JavaTimeSupplementary_bg.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_bg.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/JavaTimeSupplementary_bg.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_bg.java index c4136e0d794..3901f112e19 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/bg/JavaTimeSupplementary_bg.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_bg.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.bg; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/JavaTimeSupplementary_ca.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ca.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/JavaTimeSupplementary_ca.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ca.java index 4c8a2cbc503..61e82a03823 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ca/JavaTimeSupplementary_ca.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ca.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ca; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/JavaTimeSupplementary_cs.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_cs.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/JavaTimeSupplementary_cs.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_cs.java index 4a0194725f2..0e2fb2a979b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/cs/JavaTimeSupplementary_cs.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_cs.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.cs; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/JavaTimeSupplementary_da.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_da.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/da/JavaTimeSupplementary_da.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_da.java index 038edd324ab..0e901c9d651 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/da/JavaTimeSupplementary_da.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_da.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.da; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/JavaTimeSupplementary_de.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_de.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/JavaTimeSupplementary_de.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_de.java index b531ca80029..b3a443dd3b8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/JavaTimeSupplementary_de.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_de.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.de; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/AT/JavaTimeSupplementary_de_AT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_de_AT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/de/AT/JavaTimeSupplementary_de_AT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_de_AT.java index 3d39f03b60a..d2c7433aca4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/de/AT/JavaTimeSupplementary_de_AT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_de_AT.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.de.AT; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/JavaTimeSupplementary_el.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_el.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/el/JavaTimeSupplementary_el.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_el.java index 4ea773a2e03..6d84753086a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/el/JavaTimeSupplementary_el.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_el.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.el; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/AU/JavaTimeSupplementary_en_AU.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_AU.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/AU/JavaTimeSupplementary_en_AU.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_AU.java index b58231c6136..4ba17c167ff 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/AU/JavaTimeSupplementary_en_AU.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_AU.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.AU; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/CA/JavaTimeSupplementary_en_CA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_CA.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/CA/JavaTimeSupplementary_en_CA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_CA.java index 32162d11807..1aa0e8368d1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/CA/JavaTimeSupplementary_en_CA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_CA.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.CA; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/GB/JavaTimeSupplementary_en_GB.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_GB.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/GB/JavaTimeSupplementary_en_GB.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_GB.java index a89cecab57f..bd4dc5120a9 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/GB/JavaTimeSupplementary_en_GB.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_GB.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.GB; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IE/JavaTimeSupplementary_en_IE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_IE.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IE/JavaTimeSupplementary_en_IE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_IE.java index 8126742d78d..6afa8736120 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IE/JavaTimeSupplementary_en_IE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_IE.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.IE; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IN/JavaTimeSupplementary_en_IN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_IN.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IN/JavaTimeSupplementary_en_IN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_IN.java index af2831d2eed..afe20322842 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/IN/JavaTimeSupplementary_en_IN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_IN.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.IN; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/MT/JavaTimeSupplementary_en_MT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_MT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/MT/JavaTimeSupplementary_en_MT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_MT.java index cecbee67a3f..aca5cea5d00 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/MT/JavaTimeSupplementary_en_MT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_MT.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.MT; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/NZ/JavaTimeSupplementary_en_NZ.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_NZ.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/NZ/JavaTimeSupplementary_en_NZ.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_NZ.java index 9cfd4fa1a03..30c7f415ba6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/NZ/JavaTimeSupplementary_en_NZ.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_NZ.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.NZ; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/SG/JavaTimeSupplementary_en_SG.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_SG.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/SG/JavaTimeSupplementary_en_SG.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_SG.java index 67054dea175..0c2e8626154 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/SG/JavaTimeSupplementary_en_SG.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_SG.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.SG; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/ZA/JavaTimeSupplementary_en_ZA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_ZA.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/en/ZA/JavaTimeSupplementary_en_ZA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_ZA.java index a71b9247a6e..c30577d23ae 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/en/ZA/JavaTimeSupplementary_en_ZA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_en_ZA.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.en.ZA; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/JavaTimeSupplementary_es.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/JavaTimeSupplementary_es.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es.java index 4cfd2149ad4..461be83a264 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/JavaTimeSupplementary_es.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CL/JavaTimeSupplementary_es_CL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_CL.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CL/JavaTimeSupplementary_es_CL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_CL.java index 1078f589f85..6390b1b1eeb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CL/JavaTimeSupplementary_es_CL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_CL.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.CL; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CO/JavaTimeSupplementary_es_CO.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_CO.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CO/JavaTimeSupplementary_es_CO.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_CO.java index 1e4c5752274..788e47e5231 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/CO/JavaTimeSupplementary_es_CO.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_CO.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.CO; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/GT/JavaTimeSupplementary_es_GT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_GT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/GT/JavaTimeSupplementary_es_GT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_GT.java index c8bd8673a14..e753081ccfa 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/GT/JavaTimeSupplementary_es_GT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_GT.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.GT; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/HN/JavaTimeSupplementary_es_HN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_HN.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/HN/JavaTimeSupplementary_es_HN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_HN.java index ff2893a3aeb..4c28ef30fc8 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/HN/JavaTimeSupplementary_es_HN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_HN.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.HN; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/MX/JavaTimeSupplementary_es_MX.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_MX.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/MX/JavaTimeSupplementary_es_MX.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_MX.java index a2806fcc5d9..f1b021733f1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/MX/JavaTimeSupplementary_es_MX.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_MX.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.MX; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PA/JavaTimeSupplementary_es_PA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PA.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PA/JavaTimeSupplementary_es_PA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PA.java index d57ebce4cb6..ae6c273d3e1 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PA/JavaTimeSupplementary_es_PA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PA.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.PA; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PE/JavaTimeSupplementary_es_PE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PE.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PE/JavaTimeSupplementary_es_PE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PE.java index c4a1e2951b2..c4949c8e86e 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PE/JavaTimeSupplementary_es_PE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PE.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.PE; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PR/JavaTimeSupplementary_es_PR.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PR.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PR/JavaTimeSupplementary_es_PR.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PR.java index ff153d8ac33..0d1792716c3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/PR/JavaTimeSupplementary_es_PR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_PR.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.PR; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/UY/JavaTimeSupplementary_es_UY.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_UY.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/es/UY/JavaTimeSupplementary_es_UY.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_UY.java index c99760e80cb..2247c14e6ca 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/es/UY/JavaTimeSupplementary_es_UY.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_es_UY.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.es.UY; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/JavaTimeSupplementary_et.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_et.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/et/JavaTimeSupplementary_et.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_et.java index 28fac2f8c6f..5fd763b178c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/et/JavaTimeSupplementary_et.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_et.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.et; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/JavaTimeSupplementary_fi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fi.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/JavaTimeSupplementary_fi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fi.java index dcba6e43b39..c30940aafa3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fi/JavaTimeSupplementary_fi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fi.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.fi; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/JavaTimeSupplementary_fr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/JavaTimeSupplementary_fr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr.java index e4abbb524e3..02673f46f00 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/JavaTimeSupplementary_fr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.fr; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/BE/JavaTimeSupplementary_fr_BE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_BE.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/BE/JavaTimeSupplementary_fr_BE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_BE.java index 6eeff5c20dc..20d68a2ce2b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/BE/JavaTimeSupplementary_fr_BE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_BE.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.fr.BE; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CA/JavaTimeSupplementary_fr_CA.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_CA.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CA/JavaTimeSupplementary_fr_CA.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_CA.java index 49955afbaa3..0281c7efbff 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CA/JavaTimeSupplementary_fr_CA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_CA.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.fr.CA; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CH/JavaTimeSupplementary_fr_CH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_CH.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CH/JavaTimeSupplementary_fr_CH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_CH.java index 6c721da0a77..9a61b08c1ee 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/fr/CH/JavaTimeSupplementary_fr_CH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_fr_CH.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.fr.CH; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/JavaTimeSupplementary_ga.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ga.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/JavaTimeSupplementary_ga.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ga.java index 3b4c8c5d0c0..e9546991007 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ga/JavaTimeSupplementary_ga.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ga.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ga; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/IN/JavaTimeSupplementary_hi_IN.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hi_IN.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/IN/JavaTimeSupplementary_hi_IN.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hi_IN.java index 017a0f663d3..6f75f337a13 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hi/IN/JavaTimeSupplementary_hi_IN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hi_IN.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.hi.IN; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/JavaTimeSupplementary_hr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/JavaTimeSupplementary_hr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hr.java index bad9680f6b1..0ec012f2bad 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hr/JavaTimeSupplementary_hr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hr.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.hr; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/JavaTimeSupplementary_hu.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hu.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/JavaTimeSupplementary_hu.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hu.java index 11f28766d42..b8c81448c84 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/hu/JavaTimeSupplementary_hu.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_hu.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.hu; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/JavaTimeSupplementary_is.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_is.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/is/JavaTimeSupplementary_is.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_is.java index 3f4327aedf7..fec108a3b9d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/is/JavaTimeSupplementary_is.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_is.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.is; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/JavaTimeSupplementary_it.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_it.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/it/JavaTimeSupplementary_it.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_it.java index 5fe85246861..50f4ba1774a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/JavaTimeSupplementary_it.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_it.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.it; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/CH/JavaTimeSupplementary_it_CH.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_it_CH.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/it/CH/JavaTimeSupplementary_it_CH.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_it_CH.java index 76f60f5a506..7fa4bd2dd8f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/it/CH/JavaTimeSupplementary_it_CH.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_it_CH.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.it.CH; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/JavaTimeSupplementary_iw.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_iw.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/JavaTimeSupplementary_iw.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_iw.java index ef18ac9f211..7061f072321 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/JavaTimeSupplementary_iw.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_iw.java @@ -61,7 +61,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.iw; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/IL/JavaTimeSupplementary_iw_IL.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_iw_IL.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/IL/JavaTimeSupplementary_iw_IL.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_iw_IL.java index 56b663bfc2d..736517c3b47 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/iw/IL/JavaTimeSupplementary_iw_IL.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_iw_IL.java @@ -61,7 +61,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.iw.IL; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/JavaTimeSupplementary_ja.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ja.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/JavaTimeSupplementary_ja.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ja.java index 4b4c663bd44..b2e62a7abda 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ja/JavaTimeSupplementary_ja.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ja.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ja; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ko.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ko.java index 890ecb09399..c5a038fa1c4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ko.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ko; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/JavaTimeSupplementary_lt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_lt.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/JavaTimeSupplementary_lt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_lt.java index b9b1e053cb6..d8fdbe5d8a9 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lt/JavaTimeSupplementary_lt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_lt.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.lt; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/JavaTimeSupplementary_lv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_lv.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/JavaTimeSupplementary_lv.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_lv.java index ebd7b6edcf8..0ebd5fc2b9f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/lv/JavaTimeSupplementary_lv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_lv.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.lv; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/JavaTimeSupplementary_mk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_mk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/JavaTimeSupplementary_mk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_mk.java index 5fa27202d17..1e0308452fc 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mk/JavaTimeSupplementary_mk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_mk.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.mk; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/JavaTimeSupplementary_ms.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ms.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/JavaTimeSupplementary_ms.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ms.java index 8c24d30ea95..d672c1db720 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ms/JavaTimeSupplementary_ms.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ms.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ms; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/JavaTimeSupplementary_mt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_mt.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/JavaTimeSupplementary_mt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_mt.java index ab70398c252..5f1fafc114b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/mt/JavaTimeSupplementary_mt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_mt.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.mt; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/JavaTimeSupplementary_nl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_nl.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/JavaTimeSupplementary_nl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_nl.java index 889d4e3595f..252d1d4600f 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/JavaTimeSupplementary_nl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_nl.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.nl; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/BE/JavaTimeSupplementary_nl_BE.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_nl_BE.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/BE/JavaTimeSupplementary_nl_BE.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_nl_BE.java index b99ecfbb129..c7b1d9a0886 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/nl/BE/JavaTimeSupplementary_nl_BE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_nl_BE.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.nl.BE; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/JavaTimeSupplementary_no.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_no.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/no/JavaTimeSupplementary_no.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_no.java index 527c525f072..7f80e373735 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/no/JavaTimeSupplementary_no.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_no.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.no; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/JavaTimeSupplementary_pl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pl.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/JavaTimeSupplementary_pl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pl.java index 5425cc14d05..a66682b9c9c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pl/JavaTimeSupplementary_pl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pl.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.pl; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/JavaTimeSupplementary_pt.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pt.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/JavaTimeSupplementary_pt.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pt.java index 56cb8e3b100..9b36698caa4 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/JavaTimeSupplementary_pt.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pt.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.pt; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/PT/JavaTimeSupplementary_pt_PT.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pt_PT.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/PT/JavaTimeSupplementary_pt_PT.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pt_PT.java index fa165ee50ec..2063efc3a07 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/pt/PT/JavaTimeSupplementary_pt_PT.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_pt_PT.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.pt.PT; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/JavaTimeSupplementary_ro.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ro.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/JavaTimeSupplementary_ro.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ro.java index 40f91d0edf7..5c6ea289612 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ro/JavaTimeSupplementary_ro.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ro.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ro; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ru.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ru.java index b8d72a8ecb8..5cc7887c1e0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_ru.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.ru; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/JavaTimeSupplementary_sk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/JavaTimeSupplementary_sk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sk.java index 6e3f83cd156..a3accc1992c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sk/JavaTimeSupplementary_sk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sk.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.sk; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/JavaTimeSupplementary_sl.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sl.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/JavaTimeSupplementary_sl.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sl.java index e0edccb423c..64e3d9dbbcf 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sl/JavaTimeSupplementary_sl.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sl.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.sl; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/JavaTimeSupplementary_sq.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sq.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/JavaTimeSupplementary_sq.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sq.java index 8416d176da4..2b567b9c9d6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sq/JavaTimeSupplementary_sq.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sq.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.sq; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sr.java index 8c5fcd96f93..d5d0f0f5f8a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sr.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.sr; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr_Latn.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sr_Latn.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr_Latn.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sr_Latn.java index b0b49db808c..8957debc838 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr_Latn.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sr_Latn.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.sr; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/JavaTimeSupplementary_sv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sv.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/JavaTimeSupplementary_sv.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sv.java index 8afbe1d7421..d6ad85ba50c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/sv/JavaTimeSupplementary_sv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_sv.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.sv; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_th.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_th.java index 1c5ed80a1d2..2a4ddb9e711 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_th.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.th; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/JavaTimeSupplementary_tr.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_tr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/JavaTimeSupplementary_tr.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_tr.java index a7a05d628dd..e5b6f8590fd 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/tr/JavaTimeSupplementary_tr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_tr.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.tr; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/JavaTimeSupplementary_uk.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_uk.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/JavaTimeSupplementary_uk.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_uk.java index d6ec87f7f6c..e3976dafb1d 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/uk/JavaTimeSupplementary_uk.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_uk.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.uk; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/JavaTimeSupplementary_vi.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_vi.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/JavaTimeSupplementary_vi.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_vi.java index d6fb3d48f2f..88b270f09b6 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/vi/JavaTimeSupplementary_vi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_vi.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.vi; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_zh.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_zh.java index 819c6df6ed6..4d1f8bb4eaa 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_zh.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.zh; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/JavaTimeSupplementary_zh_TW.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_zh_TW.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/JavaTimeSupplementary_zh_TW.java rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_zh_TW.java index 8508f15f839..591b0e42455 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/zh/TW/JavaTimeSupplementary_zh_TW.java +++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/JavaTimeSupplementary_zh_TW.java @@ -65,7 +65,7 @@ // Note: this file has been generated by a tool. -package sun.text.resources.zh.TW; +package sun.text.resources.ext; import sun.util.resources.OpenListResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/th/thai_dict b/jdk/src/jdk.localedata/share/classes/sun/text/resources/thai_dict similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/text/resources/th/thai_dict rename to jdk/src/jdk.localedata/share/classes/sun/text/resources/thai_dict diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/CalendarData_ar.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ar.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/CalendarData_ar.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ar.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/be/CalendarData_be.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_be.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/be/CalendarData_be.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_be.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/bg/CalendarData_bg.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_bg.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/bg/CalendarData_bg.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_bg.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ca/CalendarData_ca.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ca.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ca/CalendarData_ca.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ca.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/cs/CalendarData_cs.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_cs.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/cs/CalendarData_cs.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_cs.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/da/CalendarData_da.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_da.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/da/CalendarData_da.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_da.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/CalendarData_de.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_de.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/CalendarData_de.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_de.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CalendarData_el.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_el.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CalendarData_el.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_el.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CY/CalendarData_el_CY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_el_CY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CY/CalendarData_el_CY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_el_CY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/CalendarData_en_GB.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_en_GB.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/CalendarData_en_GB.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_en_GB.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/CalendarData_en_IE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_en_IE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/CalendarData_en_IE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_en_IE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/MT/CalendarData_en_MT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_en_MT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/MT/CalendarData_en_MT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_en_MT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CalendarData_es.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_es.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CalendarData_es.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_es.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/ES/CalendarData_es_ES.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_es_ES.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/ES/CalendarData_es_ES.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_es_ES.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/US/CalendarData_es_US.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_es_US.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/US/CalendarData_es_US.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_es_US.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/et/CalendarData_et.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_et.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/et/CalendarData_et.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_et.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fi/CalendarData_fi.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_fi.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fi/CalendarData_fi.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_fi.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CalendarData_fr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_fr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CalendarData_fr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_fr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CA/CalendarData_fr_CA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_fr_CA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CA/CalendarData_fr_CA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_fr_CA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/CalendarData_hi.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_hi.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/CalendarData_hi.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_hi.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hr/CalendarData_hr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_hr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hr/CalendarData_hr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_hr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hu/CalendarData_hu.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_hu.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hu/CalendarData_hu.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_hu.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/in/ID/CalendarData_in_ID.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_in_ID.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/in/ID/CalendarData_in_ID.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_in_ID.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/is/CalendarData_is.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_is.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/is/CalendarData_is.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_is.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/CalendarData_it.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_it.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/it/CalendarData_it.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_it.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/iw/CalendarData_iw.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_iw.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/iw/CalendarData_iw.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_iw.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/CalendarData_ja.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ja.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/CalendarData_ja.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ja.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/CalendarData_ko.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ko.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/CalendarData_ko.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ko.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/lt/CalendarData_lt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_lt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/lt/CalendarData_lt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_lt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/lv/CalendarData_lv.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_lv.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/lv/CalendarData_lv.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_lv.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mk/CalendarData_mk.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_mk.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mk/CalendarData_mk.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_mk.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ms/MY/CalendarData_ms_MY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ms_MY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ms/MY/CalendarData_ms_MY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ms_MY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/CalendarData_mt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_mt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/CalendarData_mt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_mt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/MT/CalendarData_mt_MT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_mt_MT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/MT/CalendarData_mt_MT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_mt_MT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/CalendarData_nl.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_nl.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/CalendarData_nl.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_nl.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/no/CalendarData_no.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_no.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/no/CalendarData_no.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_no.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pl/CalendarData_pl.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pl.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pl/CalendarData_pl.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pl.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/CalendarData_pt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/CalendarData_pt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/CalendarData_pt_BR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pt_BR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/CalendarData_pt_BR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pt_BR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/PT/CalendarData_pt_PT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pt_PT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/PT/CalendarData_pt_PT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_pt_PT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ro/CalendarData_ro.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ro.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ro/CalendarData_ro.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ro.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ru/CalendarData_ru.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ru.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ru/CalendarData_ru.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_ru.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sk/CalendarData_sk.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sk.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sk/CalendarData_sk.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sk.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sl/CalendarData_sl.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sl.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sl/CalendarData_sl.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sl.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sq/CalendarData_sq.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sq.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sq/CalendarData_sq.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sq.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/CalendarData_sr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/CalendarData_sr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/BA/CalendarData_sr_Latn_BA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr_Latn_BA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/BA/CalendarData_sr_Latn_BA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr_Latn_BA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/ME/CalendarData_sr_Latn_ME.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr_Latn_ME.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/ME/CalendarData_sr_Latn_ME.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr_Latn_ME.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/RS/CalendarData_sr_Latn_RS.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr_Latn_RS.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/RS/CalendarData_sr_Latn_RS.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sr_Latn_RS.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/CalendarData_sv.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sv.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/CalendarData_sv.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_sv.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/th/CalendarData_th.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_th.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/th/CalendarData_th.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_th.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/tr/CalendarData_tr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_tr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/tr/CalendarData_tr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_tr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/uk/CalendarData_uk.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_uk.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/uk/CalendarData_uk.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_uk.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/vi/CalendarData_vi.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_vi.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/vi/CalendarData_vi.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_vi.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CalendarData_zh.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_zh.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CalendarData_zh.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CalendarData_zh.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/AE/CurrencyNames_ar_AE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_AE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/AE/CurrencyNames_ar_AE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_AE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/BH/CurrencyNames_ar_BH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_BH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/BH/CurrencyNames_ar_BH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_BH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/DZ/CurrencyNames_ar_DZ.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_DZ.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/DZ/CurrencyNames_ar_DZ.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_DZ.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/EG/CurrencyNames_ar_EG.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_EG.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/EG/CurrencyNames_ar_EG.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_EG.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/IQ/CurrencyNames_ar_IQ.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_IQ.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/IQ/CurrencyNames_ar_IQ.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_IQ.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/JO/CurrencyNames_ar_JO.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_JO.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/JO/CurrencyNames_ar_JO.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_JO.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/KW/CurrencyNames_ar_KW.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_KW.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/KW/CurrencyNames_ar_KW.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_KW.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/LB/CurrencyNames_ar_LB.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_LB.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/LB/CurrencyNames_ar_LB.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_LB.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/LY/CurrencyNames_ar_LY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_LY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/LY/CurrencyNames_ar_LY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_LY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/MA/CurrencyNames_ar_MA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_MA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/MA/CurrencyNames_ar_MA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_MA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/OM/CurrencyNames_ar_OM.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_OM.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/OM/CurrencyNames_ar_OM.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_OM.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/QA/CurrencyNames_ar_QA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_QA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/QA/CurrencyNames_ar_QA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_QA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/SA/CurrencyNames_ar_SA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_SA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/SA/CurrencyNames_ar_SA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_SA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/SD/CurrencyNames_ar_SD.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_SD.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/SD/CurrencyNames_ar_SD.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_SD.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/SY/CurrencyNames_ar_SY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_SY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/SY/CurrencyNames_ar_SY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_SY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/TN/CurrencyNames_ar_TN.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_TN.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/TN/CurrencyNames_ar_TN.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_TN.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/YE/CurrencyNames_ar_YE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_YE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/YE/CurrencyNames_ar_YE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ar_YE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/be/BY/CurrencyNames_be_BY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_be_BY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/be/BY/CurrencyNames_be_BY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_be_BY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/bg/BG/CurrencyNames_bg_BG.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_bg_BG.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/bg/BG/CurrencyNames_bg_BG.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_bg_BG.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ca/ES/CurrencyNames_ca_ES.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ca_ES.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ca/ES/CurrencyNames_ca_ES.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ca_ES.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/cs/CZ/CurrencyNames_cs_CZ.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_cs_CZ.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/cs/CZ/CurrencyNames_cs_CZ.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_cs_CZ.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/da/DK/CurrencyNames_da_DK.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_da_DK.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/da/DK/CurrencyNames_da_DK.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_da_DK.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/CurrencyNames_de.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/CurrencyNames_de.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/AT/CurrencyNames_de_AT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_AT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/AT/CurrencyNames_de_AT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_AT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/CH/CurrencyNames_de_CH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_CH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/CH/CurrencyNames_de_CH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_CH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/DE/CurrencyNames_de_DE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_DE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/DE/CurrencyNames_de_DE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_DE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/GR/CurrencyNames_de_GR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_GR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/GR/CurrencyNames_de_GR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_GR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/LU/CurrencyNames_de_LU.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_LU.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/LU/CurrencyNames_de_LU.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_de_LU.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CY/CurrencyNames_el_CY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_el_CY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CY/CurrencyNames_el_CY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_el_CY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/el/GR/CurrencyNames_el_GR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_el_GR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/el/GR/CurrencyNames_el_GR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_el_GR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/AU/CurrencyNames_en_AU.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_AU.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/AU/CurrencyNames_en_AU.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_AU.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/CA/CurrencyNames_en_CA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_CA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/CA/CurrencyNames_en_CA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_CA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/CurrencyNames_en_GB.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_GB.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/CurrencyNames_en_GB.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_GB.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/CurrencyNames_en_IE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_IE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/CurrencyNames_en_IE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_IE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IN/CurrencyNames_en_IN.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_IN.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IN/CurrencyNames_en_IN.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_IN.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/MT/CurrencyNames_en_MT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_MT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/MT/CurrencyNames_en_MT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_MT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/NZ/CurrencyNames_en_NZ.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_NZ.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/NZ/CurrencyNames_en_NZ.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_NZ.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/PH/CurrencyNames_en_PH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_PH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/PH/CurrencyNames_en_PH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_PH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/SG/CurrencyNames_en_SG.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_SG.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/SG/CurrencyNames_en_SG.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_SG.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/ZA/CurrencyNames_en_ZA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_ZA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/ZA/CurrencyNames_en_ZA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_en_ZA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CurrencyNames_es.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CurrencyNames_es.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/AR/CurrencyNames_es_AR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_AR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/AR/CurrencyNames_es_AR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_AR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/BO/CurrencyNames_es_BO.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_BO.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/BO/CurrencyNames_es_BO.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_BO.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CL/CurrencyNames_es_CL.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CL.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CL/CurrencyNames_es_CL.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CL.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CO/CurrencyNames_es_CO.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CO.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CO/CurrencyNames_es_CO.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CO.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CR/CurrencyNames_es_CR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CR/CurrencyNames_es_CR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CU/CurrencyNames_es_CU.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CU.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/CU/CurrencyNames_es_CU.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_CU.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/DO/CurrencyNames_es_DO.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_DO.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/DO/CurrencyNames_es_DO.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_DO.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/EC/CurrencyNames_es_EC.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_EC.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/EC/CurrencyNames_es_EC.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_EC.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/ES/CurrencyNames_es_ES.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_ES.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/ES/CurrencyNames_es_ES.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_ES.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/GT/CurrencyNames_es_GT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_GT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/GT/CurrencyNames_es_GT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_GT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/HN/CurrencyNames_es_HN.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_HN.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/HN/CurrencyNames_es_HN.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_HN.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/MX/CurrencyNames_es_MX.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_MX.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/MX/CurrencyNames_es_MX.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_MX.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/NI/CurrencyNames_es_NI.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_NI.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/NI/CurrencyNames_es_NI.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_NI.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PA/CurrencyNames_es_PA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PA/CurrencyNames_es_PA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PE/CurrencyNames_es_PE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PE/CurrencyNames_es_PE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PR/CurrencyNames_es_PR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PR/CurrencyNames_es_PR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PY/CurrencyNames_es_PY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/PY/CurrencyNames_es_PY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_PY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/SV/CurrencyNames_es_SV.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_SV.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/SV/CurrencyNames_es_SV.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_SV.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/US/CurrencyNames_es_US.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_US.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/US/CurrencyNames_es_US.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_US.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/UY/CurrencyNames_es_UY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_UY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/UY/CurrencyNames_es_UY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_UY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/VE/CurrencyNames_es_VE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_VE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/VE/CurrencyNames_es_VE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_es_VE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/et/EE/CurrencyNames_et_EE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_et_EE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/et/EE/CurrencyNames_et_EE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_et_EE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fi/FI/CurrencyNames_fi_FI.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fi_FI.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fi/FI/CurrencyNames_fi_FI.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fi_FI.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CurrencyNames_fr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CurrencyNames_fr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/BE/CurrencyNames_fr_BE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_BE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/BE/CurrencyNames_fr_BE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_BE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CA/CurrencyNames_fr_CA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_CA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CA/CurrencyNames_fr_CA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_CA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CH/CurrencyNames_fr_CH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_CH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/CH/CurrencyNames_fr_CH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_CH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/FR/CurrencyNames_fr_FR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_FR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/FR/CurrencyNames_fr_FR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_FR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/LU/CurrencyNames_fr_LU.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_LU.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/LU/CurrencyNames_fr_LU.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_fr_LU.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ga/IE/CurrencyNames_ga_IE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ga_IE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ga/IE/CurrencyNames_ga_IE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ga_IE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/IN/CurrencyNames_hi_IN.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_hi_IN.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/IN/CurrencyNames_hi_IN.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_hi_IN.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hr/HR/CurrencyNames_hr_HR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_hr_HR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hr/HR/CurrencyNames_hr_HR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_hr_HR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hu/HU/CurrencyNames_hu_HU.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_hu_HU.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hu/HU/CurrencyNames_hu_HU.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_hu_HU.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/in/ID/CurrencyNames_in_ID.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_in_ID.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/in/ID/CurrencyNames_in_ID.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_in_ID.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/is/IS/CurrencyNames_is_IS.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_is_IS.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/is/IS/CurrencyNames_is_IS.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_is_IS.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/CurrencyNames_it.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_it.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/it/CurrencyNames_it.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_it.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/CH/CurrencyNames_it_CH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_it_CH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/it/CH/CurrencyNames_it_CH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_it_CH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/IT/CurrencyNames_it_IT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_it_IT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/it/IT/CurrencyNames_it_IT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_it_IT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/iw/IL/CurrencyNames_iw_IL.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_iw_IL.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/iw/IL/CurrencyNames_iw_IL.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_iw_IL.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/CurrencyNames_ja.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ja.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/CurrencyNames_ja.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ja.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/JP/CurrencyNames_ja_JP.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ja_JP.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/JP/CurrencyNames_ja_JP.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ja_JP.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/CurrencyNames_ko.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ko.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/CurrencyNames_ko.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ko.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/KR/CurrencyNames_ko_KR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ko_KR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/KR/CurrencyNames_ko_KR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ko_KR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/lt/LT/CurrencyNames_lt_LT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_lt_LT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/lt/LT/CurrencyNames_lt_LT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_lt_LT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/lv/LV/CurrencyNames_lv_LV.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_lv_LV.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/lv/LV/CurrencyNames_lv_LV.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_lv_LV.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mk/MK/CurrencyNames_mk_MK.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_mk_MK.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mk/MK/CurrencyNames_mk_MK.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_mk_MK.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ms/MY/CurrencyNames_ms_MY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ms_MY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ms/MY/CurrencyNames_ms_MY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ms_MY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/MT/CurrencyNames_mt_MT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_mt_MT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/MT/CurrencyNames_mt_MT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_mt_MT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/BE/CurrencyNames_nl_BE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_nl_BE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/BE/CurrencyNames_nl_BE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_nl_BE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/NL/CurrencyNames_nl_NL.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_nl_NL.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/NL/CurrencyNames_nl_NL.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_nl_NL.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/no/NO/CurrencyNames_no_NO.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_no_NO.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/no/NO/CurrencyNames_no_NO.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_no_NO.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pl/PL/CurrencyNames_pl_PL.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pl_PL.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pl/PL/CurrencyNames_pl_PL.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pl_PL.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/CurrencyNames_pt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/CurrencyNames_pt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/CurrencyNames_pt_BR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pt_BR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/CurrencyNames_pt_BR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pt_BR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/PT/CurrencyNames_pt_PT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pt_PT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/PT/CurrencyNames_pt_PT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_pt_PT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ro/RO/CurrencyNames_ro_RO.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ro_RO.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ro/RO/CurrencyNames_ro_RO.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ro_RO.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ru/RU/CurrencyNames_ru_RU.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ru_RU.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ru/RU/CurrencyNames_ru_RU.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_ru_RU.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sk/SK/CurrencyNames_sk_SK.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sk_SK.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sk/SK/CurrencyNames_sk_SK.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sk_SK.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sl/SI/CurrencyNames_sl_SI.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sl_SI.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sl/SI/CurrencyNames_sl_SI.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sl_SI.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sq/AL/CurrencyNames_sq_AL.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sq_AL.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sq/AL/CurrencyNames_sq_AL.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sq_AL.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/BA/CurrencyNames_sr_BA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_BA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/BA/CurrencyNames_sr_BA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_BA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/CS/CurrencyNames_sr_CS.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_CS.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/CS/CurrencyNames_sr_CS.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_CS.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/BA/CurrencyNames_sr_Latn_BA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_Latn_BA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/BA/CurrencyNames_sr_Latn_BA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_Latn_BA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/ME/CurrencyNames_sr_Latn_ME.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_Latn_ME.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/ME/CurrencyNames_sr_Latn_ME.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_Latn_ME.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/RS/CurrencyNames_sr_Latn_RS.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_Latn_RS.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/RS/CurrencyNames_sr_Latn_RS.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_Latn_RS.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/ME/CurrencyNames_sr_ME.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_ME.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/ME/CurrencyNames_sr_ME.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_ME.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/RS/CurrencyNames_sr_RS.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_RS.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/RS/CurrencyNames_sr_RS.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sr_RS.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/CurrencyNames_sv.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sv.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/CurrencyNames_sv.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sv.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/SE/CurrencyNames_sv_SE.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sv_SE.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/SE/CurrencyNames_sv_SE.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_sv_SE.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/th/TH/CurrencyNames_th_TH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_th_TH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/th/TH/CurrencyNames_th_TH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_th_TH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/tr/TR/CurrencyNames_tr_TR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_tr_TR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/tr/TR/CurrencyNames_tr_TR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_tr_TR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/uk/UA/CurrencyNames_uk_UA.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_uk_UA.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/uk/UA/CurrencyNames_uk_UA.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_uk_UA.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/vi/VN/CurrencyNames_vi_VN.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_vi_VN.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/vi/VN/CurrencyNames_vi_VN.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_vi_VN.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CN/CurrencyNames_zh_CN.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_CN.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CN/CurrencyNames_zh_CN.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_CN.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/CurrencyNames_zh_HK.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_HK.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/CurrencyNames_zh_HK.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_HK.java index f33a651a40b..8e437181cc0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/CurrencyNames_zh_HK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_HK.java @@ -75,7 +75,7 @@ * */ -package sun.util.resources.zh.HK; +package sun.util.resources.ext; import java.util.Locale; import java.util.ResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/SG/CurrencyNames_zh_SG.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_SG.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/SG/CurrencyNames_zh_SG.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_SG.java index 824c930fdd9..433f626e406 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/SG/CurrencyNames_zh_SG.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_SG.java @@ -23,7 +23,7 @@ * questions. */ -package sun.util.resources.zh.SG; +package sun.util.resources.ext; import java.util.Locale; import java.util.ResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/CurrencyNames_zh_TW.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_TW.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/CurrencyNames_zh_TW.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/CurrencyNames_zh_TW.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/LocaleNames_ar.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ar.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ar/LocaleNames_ar.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ar.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/be/LocaleNames_be.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_be.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/be/LocaleNames_be.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_be.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/bg/LocaleNames_bg.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_bg.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/bg/LocaleNames_bg.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_bg.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ca/LocaleNames_ca.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ca.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ca/LocaleNames_ca.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ca.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/cs/LocaleNames_cs.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_cs.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/cs/LocaleNames_cs.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_cs.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/da/LocaleNames_da.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_da.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/da/LocaleNames_da.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_da.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/LocaleNames_de.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/LocaleNames_de.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/el/LocaleNames_el.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_el.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/el/LocaleNames_el.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_el.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CY/LocaleNames_el_CY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_el_CY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/el/CY/LocaleNames_el_CY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_el_CY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/MT/LocaleNames_en_MT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_en_MT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/MT/LocaleNames_en_MT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_en_MT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/PH/LocaleNames_en_PH.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_en_PH.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/PH/LocaleNames_en_PH.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_en_PH.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/SG/LocaleNames_en_SG.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_en_SG.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/SG/LocaleNames_en_SG.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_en_SG.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/LocaleNames_es.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_es.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/LocaleNames_es.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_es.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/US/LocaleNames_es_US.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_es_US.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/US/LocaleNames_es_US.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_es_US.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/et/LocaleNames_et.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_et.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/et/LocaleNames_et.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_et.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fi/LocaleNames_fi.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_fi.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fi/LocaleNames_fi.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_fi.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/LocaleNames_fr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_fr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/LocaleNames_fr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_fr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ga/LocaleNames_ga.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ga.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ga/LocaleNames_ga.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ga.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/LocaleNames_hi.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_hi.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/LocaleNames_hi.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_hi.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hr/LocaleNames_hr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_hr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hr/LocaleNames_hr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_hr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hu/LocaleNames_hu.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_hu.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hu/LocaleNames_hu.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_hu.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/in/LocaleNames_in.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_in.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/in/LocaleNames_in.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_in.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/is/LocaleNames_is.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_is.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/is/LocaleNames_is.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_is.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/LocaleNames_it.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_it.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/it/LocaleNames_it.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_it.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/iw/LocaleNames_iw.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_iw.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/iw/LocaleNames_iw.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_iw.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/LocaleNames_ja.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ja.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/LocaleNames_ja.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ja.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/LocaleNames_ko.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ko.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/LocaleNames_ko.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ko.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/lt/LocaleNames_lt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_lt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/lt/LocaleNames_lt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_lt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/lv/LocaleNames_lv.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_lv.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/lv/LocaleNames_lv.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_lv.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mk/LocaleNames_mk.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_mk.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mk/LocaleNames_mk.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_mk.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ms/LocaleNames_ms.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ms.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ms/LocaleNames_ms.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ms.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/LocaleNames_mt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_mt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/mt/LocaleNames_mt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_mt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/LocaleNames_nl.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_nl.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/nl/LocaleNames_nl.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_nl.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/no/LocaleNames_no.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_no.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/no/LocaleNames_no.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_no.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/no/NO/LocaleNames_no_NO_NY.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_no_NO_NY.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/no/NO/LocaleNames_no_NO_NY.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_no_NO_NY.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pl/LocaleNames_pl.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pl.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pl/LocaleNames_pl.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pl.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/LocaleNames_pt.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pt.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/LocaleNames_pt.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pt.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/LocaleNames_pt_BR.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pt_BR.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/LocaleNames_pt_BR.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pt_BR.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/PT/LocaleNames_pt_PT.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pt_PT.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/PT/LocaleNames_pt_PT.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_pt_PT.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ro/LocaleNames_ro.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ro.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ro/LocaleNames_ro.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ro.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ru/LocaleNames_ru.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ru.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ru/LocaleNames_ru.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_ru.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sk/LocaleNames_sk.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sk.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sk/LocaleNames_sk.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sk.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sl/LocaleNames_sl.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sl.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sl/LocaleNames_sl.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sl.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sq/LocaleNames_sq.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sq.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sq/LocaleNames_sq.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sq.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/LocaleNames_sr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/LocaleNames_sr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/LocaleNames_sr_Latn.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sr_Latn.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sr/LocaleNames_sr_Latn.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sr_Latn.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/LocaleNames_sv.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/LocaleNames_sv.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/th/LocaleNames_th.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_th.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/th/LocaleNames_th.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_th.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/tr/LocaleNames_tr.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_tr.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/tr/LocaleNames_tr.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_tr.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/uk/LocaleNames_uk.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_uk.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/uk/LocaleNames_uk.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_uk.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/vi/LocaleNames_vi.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_vi.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/vi/LocaleNames_vi.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_vi.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/LocaleNames_zh.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/LocaleNames_zh.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/LocaleNames_zh_HK.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_HK.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/LocaleNames_zh_HK.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_HK.java index 5866e3a3862..306582406bb 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/LocaleNames_zh_HK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_HK.java @@ -23,7 +23,7 @@ * questions. */ -package sun.util.resources.zh.HK; +package sun.util.resources.ext; import java.util.Locale; import java.util.ResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/SG/LocaleNames_zh_SG.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_SG.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/SG/LocaleNames_zh_SG.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_SG.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/LocaleNames_zh_TW.properties b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_TW.properties similarity index 100% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/LocaleNames_zh_TW.properties rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_zh_TW.properties diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java index 8fa22f926f5..0f3ee8ba04a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.de; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/CA/TimeZoneNames_en_CA.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_CA.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/CA/TimeZoneNames_en_CA.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_CA.java index 12328cc8c13..0e35d5045d0 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/CA/TimeZoneNames_en_CA.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_CA.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.en.CA; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/TimeZoneNames_en_GB.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_GB.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/TimeZoneNames_en_GB.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_GB.java index cd5b9bb2637..43922dcb032 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/GB/TimeZoneNames_en_GB.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_GB.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.en.GB; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/TimeZoneNames_en_IE.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_IE.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/TimeZoneNames_en_IE.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_IE.java index a640d4d992f..e41f889190c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/en/IE/TimeZoneNames_en_IE.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_en_IE.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.en.IE; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java index c20c02e055a..e0fe7730eba 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.es; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java index 3d812007a75..627ecfc1334 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.fr; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/TimeZoneNames_hi.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_hi.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/TimeZoneNames_hi.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_hi.java index 05acbc3b4df..f47c414938a 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/hi/TimeZoneNames_hi.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_hi.java @@ -29,7 +29,7 @@ * */ -package sun.util.resources.hi; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java index 33350c43bfa..c0266387136 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.it; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java index 57a3fb7bddf..72eab6406c3 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.ja; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java index d17154b3498..5523d246f1b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.ko; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/TimeZoneNames_pt_BR.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/TimeZoneNames_pt_BR.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java index 04d56b9c2a9..c4bdbb00a64 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/BR/TimeZoneNames_pt_BR.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.pt.BR; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java index 8705bfe881b..621a7fc1a39 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.sv; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CN/TimeZoneNames_zh_CN.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CN/TimeZoneNames_zh_CN.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java index be0019b1573..1eca844f06b 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/CN/TimeZoneNames_zh_CN.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.zh.CN; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/TimeZoneNames_zh_HK.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_HK.java similarity index 98% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/TimeZoneNames_zh_HK.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_HK.java index 25faafa7731..9733c12e96c 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/HK/TimeZoneNames_zh_HK.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_HK.java @@ -36,7 +36,7 @@ * */ -package sun.util.resources.zh.HK; +package sun.util.resources.ext; import java.util.Locale; import java.util.ResourceBundle; diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/TimeZoneNames_zh_TW.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java similarity index 99% rename from jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/TimeZoneNames_zh_TW.java rename to jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java index be1de6c6fe7..9be595a9461 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TW/TimeZoneNames_zh_TW.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java @@ -38,7 +38,7 @@ * */ -package sun.util.resources.zh.TW; +package sun.util.resources.ext; import sun.util.resources.TimeZoneNamesBundle; From 2b446bf0741cb5bf02f15c2cd7fd137f5a86a700 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Sat, 20 Feb 2016 12:19:36 -0800 Subject: [PATCH 131/139] 8150014: java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java fails with NoClassDefFoundError Reviewed-by: martin, psandoz, darcy, mhaupt, dholmes --- .../share/classes/java/util/SplittableRandom.java | 8 +++++--- .../classes/java/util/concurrent/ThreadLocalRandom.java | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java index cf71c91e8da..f54b3d931b2 100644 --- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java +++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java @@ -225,9 +225,11 @@ public final class SplittableRandom { private static final AtomicLong defaultGen = new AtomicLong(initialSeed()); private static long initialSeed() { - java.security.PrivilegedAction action = - () -> Boolean.getBoolean("java.util.secureRandomSeed"); - if (java.security.AccessController.doPrivileged(action)) { + if (java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Boolean run() { + return Boolean.getBoolean("java.util.secureRandomSeed"); + }})) { byte[] seedBytes = java.security.SecureRandom.getSeed(8); long s = (long)seedBytes[0] & 0xffL; for (int i = 1; i < 8; ++i) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 90fb6cf054f..3e50171cf20 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -134,9 +134,11 @@ public class ThreadLocalRandom extends Random { private static final AtomicLong seeder = new AtomicLong(initialSeed()); private static long initialSeed() { - java.security.PrivilegedAction action = - () -> Boolean.getBoolean("java.util.secureRandomSeed"); - if (java.security.AccessController.doPrivileged(action)) { + if (java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Boolean run() { + return Boolean.getBoolean("java.util.secureRandomSeed"); + }})) { byte[] seedBytes = java.security.SecureRandom.getSeed(8); long s = (long)seedBytes[0] & 0xffL; for (int i = 1; i < 8; ++i) From 165fa0078fb69e47baf4381fe44512245e11fd93 Mon Sep 17 00:00:00 2001 From: Shilpi Rastogi Date: Mon, 22 Feb 2016 09:02:14 +0100 Subject: [PATCH 132/139] 8144931: Assert class signatures are correct and refer to valid classes Reviewed-by: vlivanov, psandoz, mhaupt --- .../lang/invoke/InvokerBytecodeGenerator.java | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 2d7a9f5ff1c..adec7ad5a50 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -611,6 +611,31 @@ class InvokerBytecodeGenerator { return true; } + static String className(String cn) { + assert checkClassName(cn): "Class not found: " + cn; + return cn; + } + + static boolean checkClassName(String cn) { + Type tp = Type.getType(cn); + // additional sanity so only valid "L;" descriptors work + if (tp.getSort() != Type.OBJECT) { + return false; + } + try { + Class c = Class.forName(tp.getClassName(), false, null); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + static final String LF_HIDDEN_SIG = className("Ljava/lang/invoke/LambdaForm$Hidden;"); + static final String LF_COMPILED_SIG = className("Ljava/lang/invoke/LambdaForm$Compiled;"); + static final String FORCEINLINE_SIG = className("Ljdk/internal/vm/annotation/ForceInline;"); + static final String DONTINLINE_SIG = className("Ljdk/internal/vm/annotation/DontInline;"); + static final String INJECTEDPROFILE_SIG = className("Ljava/lang/invoke/InjectedProfile;"); + /** * Generate an invoker method for the passed {@link LambdaForm}. */ @@ -618,16 +643,16 @@ class InvokerBytecodeGenerator { classFilePrologue(); // Suppress this method in backtraces displayed to the user. - mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); + mv.visitAnnotation(LF_HIDDEN_SIG, true); // Mark this method as a compiled LambdaForm - mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true); + mv.visitAnnotation(LF_COMPILED_SIG, true); if (lambdaForm.forceInline) { // Force inlining of this invoker method. - mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true); + mv.visitAnnotation(FORCEINLINE_SIG, true); } else { - mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true); + mv.visitAnnotation(DONTINLINE_SIG, true); } if (lambdaForm.customized != null) { @@ -656,7 +681,7 @@ class InvokerBytecodeGenerator { if (PROFILE_GWT) { assert(name.arguments[0] instanceof Name && nameRefersTo((Name)name.arguments[0], MethodHandleImpl.class, "profileBoolean")); - mv.visitAnnotation("Ljava/lang/invoke/InjectedProfile;", true); + mv.visitAnnotation(INJECTEDPROFILE_SIG, true); } onStack = emitSelectAlternative(name, lambdaForm.names[i+1]); i++; // skip MH.invokeBasic of the selectAlternative result @@ -1306,10 +1331,10 @@ class InvokerBytecodeGenerator { classFilePrologue(); // Suppress this method in backtraces displayed to the user. - mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); + mv.visitAnnotation(LF_HIDDEN_SIG, true); // Don't inline the interpreter entry. - mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true); + mv.visitAnnotation(DONTINLINE_SIG, true); // create parameter array emitIconstInsn(invokerType.parameterCount()); @@ -1365,10 +1390,10 @@ class InvokerBytecodeGenerator { classFilePrologue(); // Suppress this method in backtraces displayed to the user. - mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); + mv.visitAnnotation(LF_HIDDEN_SIG, true); // Force inlining of this invoker method. - mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true); + mv.visitAnnotation(FORCEINLINE_SIG, true); // Load receiver emitAloadInsn(0); From 99a9fb0cb935ca55b656946a78cd6321057f0c94 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:20:46 +0200 Subject: [PATCH 133/139] Added tag jdk-9+106 for changeset 6c644cca3f3f --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c43cf5c9d3a..c0b87cffe37 100644 --- a/.hgtags +++ b/.hgtags @@ -348,3 +348,4 @@ f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 4a652e4ca9523422149958673033e0ac740d5e1e jdk-9+103 086c682bd8c5f195c324f61e2c61fbcd0226d63b jdk-9+104 db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 +6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 From bf4f843350a836e5e6f1db4d7f4ad34ea5701f1a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:46 -0800 Subject: [PATCH 134/139] Added tag jdk-9+107 for changeset e1580bae8eb5 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 5b88bcd99f8..65cb5c825bd 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -349,3 +349,4 @@ eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103 8faf1aec77a9517c69d2f4d8dd146429852ace7f jdk-9+104 55518739e399a1066c8613e19100d51b38d9f223 jdk-9+105 6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106 +8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107 From 095027bd7407253c7b86bfe7a45079cef8852b6a Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 25 Feb 2016 23:14:22 +0000 Subject: [PATCH 135/139] 8087112: HTTP API and HTTP/1.1 implementation Reviewed-by: alanb, chegar, coffeys, psandoz, rriggs --- .../classes/build/tools/module/boot.modules | 1 + .../share/classes/java/net/Authenticator.java | 42 + .../share/classes/java/net/ProxySelector.java | 45 + .../share/classes/java/net/package-info.java | 3 +- .../classes/java/net/http/AsyncEvent.java | 58 + .../java/net/http/AuthenticationFilter.java | 306 +++ .../classes/java/net/http/BufferHandler.java | 37 + .../classes/java/net/http/ConnectionPool.java | 272 +++ .../classes/java/net/http/CookieFilter.java | 66 + .../share/classes/java/net/http/Exchange.java | 419 ++++ .../classes/java/net/http/ExchangeImpl.java | 133 ++ .../java/net/http/ExecutorWrapper.java | 100 + .../classes/java/net/http/FilterFactory.java | 49 + .../classes/java/net/http/HeaderFilter.java | 45 + .../classes/java/net/http/HeaderParser.java | 245 +++ .../classes/java/net/http/Http1Exchange.java | 309 +++ .../classes/java/net/http/Http1Request.java | 362 ++++ .../classes/java/net/http/Http1Response.java | 290 +++ .../java/net/http/Http2ClientImpl.java | 33 + .../java/net/http/Http2Connection.java | 65 + .../classes/java/net/http/HttpClient.java | 415 ++++ .../java/net/http/HttpClientBuilderImpl.java | 133 ++ .../classes/java/net/http/HttpClientImpl.java | 499 +++++ .../classes/java/net/http/HttpConnection.java | 367 ++++ .../classes/java/net/http/HttpHeaders.java | 81 + .../classes/java/net/http/HttpHeaders1.java | 29 + .../java/net/http/HttpHeadersImpl.java | 136 ++ .../java/net/http/HttpRedirectImpl.java | 104 + .../classes/java/net/http/HttpRequest.java | 871 ++++++++ .../java/net/http/HttpRequestBuilderImpl.java | 177 ++ .../java/net/http/HttpRequestImpl.java | 285 +++ .../classes/java/net/http/HttpResponse.java | 977 +++++++++ .../java/net/http/HttpResponseImpl.java | 157 ++ .../java/net/http/HttpTimeoutException.java | 40 + .../share/classes/java/net/http/Log.java | 170 ++ .../classes/java/net/http/MultiExchange.java | 275 +++ .../share/classes/java/net/http/Pair.java | 46 + .../java/net/http/PlainHttpConnection.java | 228 +++ .../java/net/http/PlainProxyConnection.java | 39 + .../net/http/PlainTunnelingConnection.java | 143 ++ .../classes/java/net/http/RawChannel.java | 148 ++ .../classes/java/net/http/RedirectFilter.java | 96 + .../java/net/http/ResponseContent.java | 323 +++ .../java/net/http/ResponseHeaders.java | 480 +++++ .../classes/java/net/http/SSLConnection.java | 178 ++ .../classes/java/net/http/SSLDelegate.java | 457 +++++ .../java/net/http/SSLTunnelConnection.java | 179 ++ .../share/classes/java/net/http/Stream.java | 101 + .../classes/java/net/http/TimeoutEvent.java | 47 + .../share/classes/java/net/http/Utils.java | 221 ++ .../classes/java/net/http/package-info.java | 40 + .../sun/net/httpserver/FileServerHandler.java | 80 +- jdk/test/java/net/httpclient/APIErrors.java | 207 ++ .../java/net/httpclient/BasicAuthTest.java | 162 ++ jdk/test/java/net/httpclient/HeadersTest.java | 64 + jdk/test/java/net/httpclient/HttpUtils.java | 174 ++ .../java/net/httpclient/ImmutableHeaders.java | 116 ++ .../net/httpclient/LightWeightHttpServer.java | 313 +++ .../java/net/httpclient/ManyRequests.java | 194 ++ jdk/test/java/net/httpclient/ProxyServer.java | 319 +++ .../java/net/httpclient/QuickResponses.java | 104 + .../java/net/httpclient/RequestBodyTest.java | 169 ++ jdk/test/java/net/httpclient/Server.java | 259 +++ jdk/test/java/net/httpclient/SmokeTest.java | 949 +++++++++ .../java/net/httpclient/SplitResponse.java | 117 ++ jdk/test/java/net/httpclient/TimeoutTest.java | 158 ++ .../java/net/httpclient/docs/files/foo.txt | 1 + .../httpclient/docs/files/notsobigfile.txt | 34 + .../net/httpclient/docs/files/smallfile.txt | 1792 +++++++++++++++++ .../java/net/httpclient/security/0.policy | 24 + .../java/net/httpclient/security/1.policy | 24 + .../java/net/httpclient/security/10.policy | 22 + .../java/net/httpclient/security/11.policy | 24 + .../java/net/httpclient/security/12.policy | 24 + .../java/net/httpclient/security/15.policy | 27 + .../java/net/httpclient/security/2.policy | 24 + .../java/net/httpclient/security/3.policy | 24 + .../java/net/httpclient/security/4.policy | 25 + .../java/net/httpclient/security/5.policy | 24 + .../java/net/httpclient/security/6.policy | 24 + .../java/net/httpclient/security/7.policy | 24 + .../java/net/httpclient/security/8.policy | 24 + .../java/net/httpclient/security/9.policy | 24 + .../net/httpclient/security/Security.java | 475 +++++ 84 files changed, 16343 insertions(+), 4 deletions(-) create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Log.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Pair.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Stream.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Utils.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/package-info.java create mode 100644 jdk/test/java/net/httpclient/APIErrors.java create mode 100644 jdk/test/java/net/httpclient/BasicAuthTest.java create mode 100644 jdk/test/java/net/httpclient/HeadersTest.java create mode 100644 jdk/test/java/net/httpclient/HttpUtils.java create mode 100644 jdk/test/java/net/httpclient/ImmutableHeaders.java create mode 100644 jdk/test/java/net/httpclient/LightWeightHttpServer.java create mode 100644 jdk/test/java/net/httpclient/ManyRequests.java create mode 100644 jdk/test/java/net/httpclient/ProxyServer.java create mode 100644 jdk/test/java/net/httpclient/QuickResponses.java create mode 100644 jdk/test/java/net/httpclient/RequestBodyTest.java create mode 100644 jdk/test/java/net/httpclient/Server.java create mode 100644 jdk/test/java/net/httpclient/SmokeTest.java create mode 100644 jdk/test/java/net/httpclient/SplitResponse.java create mode 100644 jdk/test/java/net/httpclient/TimeoutTest.java create mode 100644 jdk/test/java/net/httpclient/docs/files/foo.txt create mode 100644 jdk/test/java/net/httpclient/docs/files/notsobigfile.txt create mode 100644 jdk/test/java/net/httpclient/docs/files/smallfile.txt create mode 100644 jdk/test/java/net/httpclient/security/0.policy create mode 100644 jdk/test/java/net/httpclient/security/1.policy create mode 100644 jdk/test/java/net/httpclient/security/10.policy create mode 100644 jdk/test/java/net/httpclient/security/11.policy create mode 100644 jdk/test/java/net/httpclient/security/12.policy create mode 100644 jdk/test/java/net/httpclient/security/15.policy create mode 100644 jdk/test/java/net/httpclient/security/2.policy create mode 100644 jdk/test/java/net/httpclient/security/3.policy create mode 100644 jdk/test/java/net/httpclient/security/4.policy create mode 100644 jdk/test/java/net/httpclient/security/5.policy create mode 100644 jdk/test/java/net/httpclient/security/6.policy create mode 100644 jdk/test/java/net/httpclient/security/7.policy create mode 100644 jdk/test/java/net/httpclient/security/8.policy create mode 100644 jdk/test/java/net/httpclient/security/9.policy create mode 100644 jdk/test/java/net/httpclient/security/Security.java diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index f7f21225a5d..a22b4af52b9 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -2,6 +2,7 @@ java.base java.compiler java.datatransfer java.desktop +java.httpclient java.instrument java.logging java.management diff --git a/jdk/src/java.base/share/classes/java/net/Authenticator.java b/jdk/src/java.base/share/classes/java/net/Authenticator.java index e62e169099c..8b59db010f3 100644 --- a/jdk/src/java.base/share/classes/java/net/Authenticator.java +++ b/jdk/src/java.base/share/classes/java/net/Authenticator.java @@ -319,6 +319,48 @@ class Authenticator { } } + /** + * Ask this authenticator for a password. + * + * @param host The hostname of the site requesting authentication. + * @param addr The InetAddress of the site requesting authorization, + * or null if not known. + * @param port the port for the requested connection + * @param protocol The protocol that's requesting the connection + * ({@link java.net.Authenticator#getRequestingProtocol()}) + * @param prompt A prompt string for the user + * @param scheme The authentication scheme + * @param url The requesting URL that caused the authentication + * @param reqType The type (server or proxy) of the entity requesting + * authentication. + * + * @return The username/password, or null if one can't be gotten + * + * @since 9 + */ + public PasswordAuthentication + requestPasswordAuthenticationInstance(String host, + InetAddress addr, + int port, + String protocol, + String prompt, + String scheme, + URL url, + RequestorType reqType) { + synchronized (this) { + this.reset(); + this.requestingHost = host; + this.requestingSite = addr; + this.requestingPort = port; + this.requestingProtocol = protocol; + this.requestingPrompt = prompt; + this.requestingScheme = scheme; + this.requestingURL = url; + this.requestingAuthType = reqType; + return this.getPasswordAuthentication(); + } + } + /** * Gets the {@code hostname} of the * site or proxy requesting authentication, or {@code null} diff --git a/jdk/src/java.base/share/classes/java/net/ProxySelector.java b/jdk/src/java.base/share/classes/java/net/ProxySelector.java index d6bb53656fd..04c675cedc8 100644 --- a/jdk/src/java.base/share/classes/java/net/ProxySelector.java +++ b/jdk/src/java.base/share/classes/java/net/ProxySelector.java @@ -162,4 +162,49 @@ public abstract class ProxySelector { * @throws IllegalArgumentException if either argument is null */ public abstract void connectFailed(URI uri, SocketAddress sa, IOException ioe); + + /** + * Returns a ProxySelector which uses the given proxy address for all HTTP + * and HTTPS requests. If proxy is {@code null} then proxying is disabled. + * + * @param proxyAddress + * The address of the proxy + * + * @return a ProxySelector + * + * @since 9 + */ + public static ProxySelector of(InetSocketAddress proxyAddress) { + return new StaticProxySelector(proxyAddress); + } + + static class StaticProxySelector extends ProxySelector { + private static final List NO_PROXY_LIST = List.of(Proxy.NO_PROXY); + final List list; + + StaticProxySelector(InetSocketAddress address){ + Proxy p; + if (address == null) { + p = Proxy.NO_PROXY; + } else { + p = new Proxy(Proxy.Type.HTTP, address); + } + list = List.of(p); + } + + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException e) { + /* ignore */ + } + + @Override + public synchronized List select(URI uri) { + String scheme = uri.getScheme().toLowerCase(); + if (scheme.equals("http") || scheme.equals("https")) { + return list; + } else { + return NO_PROXY_LIST; + } + } + } } diff --git a/jdk/src/java.base/share/classes/java/net/package-info.java b/jdk/src/java.base/share/classes/java/net/package-info.java index 2279cca479f..37a4ea69de1 100644 --- a/jdk/src/java.base/share/classes/java/net/package-info.java +++ b/jdk/src/java.base/share/classes/java/net/package-info.java @@ -121,7 +121,8 @@ * underlying protocol handlers like http or https.
    • *
    • {@link java.net.HttpURLConnection} is a subclass of URLConnection * and provides some additional functionalities specific to the - * HTTP protocol.
    • + * HTTP protocol. This API has been superceded by the newer + HTTP client API described in the previous section. *
    *

    The recommended usage is to use {@link java.net.URI} to identify * resources, then convert it into a {@link java.net.URL} when it is time to diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java new file mode 100644 index 00000000000..1cd606fe7a5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.nio.channels.SelectableChannel; + +/** + * Event handling interface from HttpClientImpl's selector. + * + *

    If blockingChannel is true, then the channel will be put in blocking + * mode prior to handle() being called. If false, then it remains non-blocking. + */ +abstract class AsyncEvent { + + /** + * Implement this if channel should be made blocking before calling handle() + */ + public interface Blocking { } + + /** + * Implement this if channel should remain non-blocking before calling handle() + */ + public interface NonBlocking { } + + /** Returns the channel */ + public abstract SelectableChannel channel(); + + /** Returns the selector interest op flags OR'd */ + public abstract int interestOps(); + + /** Called when event occurs */ + public abstract void handle(); + + /** Called when selector is shutting down. Abort all exchanges. */ + public abstract void abort(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java new file mode 100644 index 00000000000..c06f3886a85 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import static java.net.Authenticator.RequestorType.PROXY; +import static java.net.Authenticator.RequestorType.SERVER; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.InetSocketAddress; +import java.net.URISyntaxException; +import java.util.Base64; +import java.util.HashMap; +import java.util.LinkedList; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + +/** + * Implementation of Http Basic authentication. + */ +class AuthenticationFilter implements HeaderFilter { + + static private final Base64.Encoder encoder = Base64.getEncoder(); + + static final int DEFAULT_RETRY_LIMIT = 3; + + static final int retry_limit = Utils.getIntegerNetProperty( + "sun.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT); + + static final int UNAUTHORIZED = 401; + static final int PROXY_UNAUTHORIZED = 407; + + private PasswordAuthentication getCredentials(String header, + boolean proxy, + HttpRequestImpl req) + throws IOException + { + HttpClientImpl client = req.client(); + java.net.Authenticator auth = + client.authenticator() + .orElseThrow(() -> new IOException("No authenticator set")); + URI uri = req.uri(); + HeaderParser parser = new HeaderParser(header); + String authscheme = parser.findKey(0); + + String realm = parser.findValue("realm"); + java.net.Authenticator.RequestorType rtype = proxy ? PROXY : SERVER; + + // needs to be instance method in Authenticator + return auth.requestPasswordAuthenticationInstance(uri.getHost(), + null, + uri.getPort(), + uri.getScheme(), + realm, + authscheme, + uri.toURL(), + rtype + ); + } + + private URI getProxyURI(HttpRequestImpl r) { + InetSocketAddress proxy = r.proxy(); + if (proxy == null) { + return null; + } + + // our own private scheme for proxy URLs + // eg. proxy.http://host:port/ + String scheme = "proxy." + r.uri().getScheme(); + try { + return new URI(scheme, + null, + proxy.getHostString(), + proxy.getPort(), + null, + null, + null); + } catch (URISyntaxException e) { + throw new InternalError(e); + } + } + + @Override + public void request(HttpRequestImpl r) throws IOException { + // use preemptive authentication if an entry exists. + Cache cache = getCache(r); + + // Proxy + if (r.exchange.proxyauth == null) { + URI proxyURI = getProxyURI(r); + if (proxyURI != null) { + CacheEntry ca = cache.get(proxyURI, true); + if (ca != null) { + r.exchange.proxyauth = new AuthInfo(true, ca.scheme, null, ca); + addBasicCredentials(r, true, ca.value); + } + } + } + + // Server + if (r.exchange.serverauth == null) { + CacheEntry ca = cache.get(r.uri(), false); + if (ca != null) { + r.exchange.serverauth = new AuthInfo(true, ca.scheme, null, ca); + addBasicCredentials(r, false, ca.value); + } + } + } + + // TODO: refactor into per auth scheme class + static private void addBasicCredentials(HttpRequestImpl r, + boolean proxy, + PasswordAuthentication pw) { + String hdrname = proxy ? "Proxy-Authorization" : "Authorization"; + StringBuilder sb = new StringBuilder(128); + sb.append(pw.getUserName()).append(':').append(pw.getPassword()); + String s = encoder.encodeToString(sb.toString().getBytes(ISO_8859_1)); + String value = "Basic " + s; + r.setSystemHeader(hdrname, value); + } + + // Information attached to a HttpRequestImpl relating to authentication + static class AuthInfo { + final boolean fromcache; + final String scheme; + int retries; + PasswordAuthentication credentials; // used in request + CacheEntry cacheEntry; // if used + + AuthInfo(boolean fromcache, + String scheme, + PasswordAuthentication credentials) { + this.fromcache = fromcache; + this.scheme = scheme; + this.credentials = credentials; + this.retries = 1; + } + + AuthInfo(boolean fromcache, + String scheme, + PasswordAuthentication credentials, + CacheEntry ca) { + this(fromcache, scheme, credentials); + assert credentials == null || (ca != null && ca.value == null); + cacheEntry = ca; + } + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + Cache cache = getCache(r.request); + int status = r.statusCode(); + HttpHeaders hdrs = r.headers(); + HttpRequestImpl req = r.request(); + + if (status != UNAUTHORIZED && status != PROXY_UNAUTHORIZED) { + // check if any authentication succeeded for first time + if (req.exchange.serverauth != null && !req.exchange.serverauth.fromcache) { + AuthInfo au = req.exchange.serverauth; + cache.store(au.scheme, req.uri(), false, au.credentials); + } + if (req.exchange.proxyauth != null && !req.exchange.proxyauth.fromcache) { + AuthInfo au = req.exchange.proxyauth; + cache.store(au.scheme, req.uri(), false, au.credentials); + } + return null; + } + + boolean proxy = status == PROXY_UNAUTHORIZED; + String authname = proxy ? "Proxy-Authentication" : "WWW-Authenticate"; + String authval = hdrs.firstValue(authname).orElseThrow(() -> { + return new IOException("Invalid auth header"); + }); + HeaderParser parser = new HeaderParser(authval); + String scheme = parser.findKey(0); + + // TODO: Need to generalise from Basic only. Delegate to a provider class etc. + + if (!scheme.equalsIgnoreCase("Basic")) { + return null; // error gets returned to app + } + + String realm = parser.findValue("realm"); + AuthInfo au = proxy ? req.exchange.proxyauth : req.exchange.serverauth; + if (au == null) { + PasswordAuthentication pw = getCredentials(authval, proxy, req); + if (pw == null) { + throw new IOException("No credentials provided"); + } + // No authentication in request. Get credentials from user + au = new AuthInfo(false, "Basic", pw); + if (proxy) + req.exchange.proxyauth = au; + else + req.exchange.serverauth = au; + addBasicCredentials(req, proxy, pw); + return req; + } else if (au.retries > retry_limit) { + throw new IOException("too many authentication attempts"); + } else { + // we sent credentials, but they were rejected + if (au.fromcache) { + cache.remove(au.cacheEntry); + } + // try again + au.credentials = getCredentials(authval, proxy, req); + addBasicCredentials(req, proxy, au.credentials); + au.retries++; + return req; + } + } + + static final HashMap caches = new HashMap<>(); + + static synchronized Cache getCache(HttpRequestImpl req) { + HttpClientImpl client = req.client(); + Cache c = caches.get(client); + if (c == null) { + c = new Cache(); + caches.put(client, c); + } + return c; + } + + static class Cache { + final LinkedList entries = new LinkedList<>(); + + synchronized CacheEntry get(URI uri, boolean proxy) { + for (CacheEntry entry : entries) { + if (entry.equalsKey(uri, proxy)) { + return entry; + } + } + return null; + } + + synchronized void remove(String authscheme, URI domain, boolean proxy) { + for (CacheEntry entry : entries) { + if (entry.equalsKey(domain, proxy)) { + entries.remove(entry); + } + } + } + + synchronized void remove(CacheEntry entry) { + entries.remove(entry); + } + + synchronized void store(String authscheme, + URI domain, + boolean proxy, + PasswordAuthentication value) { + remove(authscheme, domain, proxy); + entries.add(new CacheEntry(authscheme, domain, proxy, value)); + } + } + + static class CacheEntry { + final String root; + final String scheme; + final boolean proxy; + final PasswordAuthentication value; + + CacheEntry(String authscheme, + URI uri, + boolean proxy, + PasswordAuthentication value) { + this.scheme = authscheme; + this.root = uri.resolve(".").toString(); // remove extraneous components + this.proxy = proxy; + this.value = value; + } + + public PasswordAuthentication value() { + return value; + } + + public boolean equalsKey(URI uri, boolean proxy) { + if (this.proxy != proxy) { + return false; + } + String other = uri.toString(); + return other.startsWith(root); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java new file mode 100644 index 00000000000..a311422a782 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.nio.ByteBuffer; + +/** + * Implemented by buffer pools. + */ +interface BufferHandler { + + ByteBuffer getBuffer(); + + void returnBuffer(ByteBuffer buffer); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java new file mode 100644 index 00000000000..70e475ec6e3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.Objects; + +/** + * Http 1.1 connection pool. + */ +class ConnectionPool { + + static final long KEEP_ALIVE = Utils.getIntegerNetProperty( + "sun.net.httpclient.keepalive.timeout", 1200); // seconds + + // Pools of idle connections + + final HashMap> plainPool; + final HashMap> sslPool; + CacheCleaner cleaner; + + /** + * Entries in connection pool are keyed by destination address and/or + * proxy address: + * case 1: plain TCP not via proxy (destination only) + * case 2: plain TCP via proxy (proxy only) + * case 3: SSL not via proxy (destination only) + * case 4: SSL over tunnel (destination and proxy) + */ + static class CacheKey { + final InetSocketAddress proxy; + final InetSocketAddress destination; + + CacheKey(InetSocketAddress destination, InetSocketAddress proxy) { + this.proxy = proxy; + this.destination = destination; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final CacheKey other = (CacheKey) obj; + if (!Objects.equals(this.proxy, other.proxy)) { + return false; + } + if (!Objects.equals(this.destination, other.destination)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return Objects.hash(proxy, destination); + } + } + + static class ExpiryEntry { + final HttpConnection connection; + final long expiry; // absolute time in seconds of expiry time + ExpiryEntry(HttpConnection connection, long expiry) { + this.connection = connection; + this.expiry = expiry; + } + } + + final LinkedList expiryList; + + /** + * There should be one of these per HttpClient. + */ + ConnectionPool() { + plainPool = new HashMap<>(); + sslPool = new HashMap<>(); + expiryList = new LinkedList<>(); + cleaner = new CacheCleaner(); + } + + void start() { + cleaner.start(); + } + + static CacheKey cacheKey(InetSocketAddress destination, + InetSocketAddress proxy) { + return new CacheKey(destination, proxy); + } + + synchronized HttpConnection getConnection(boolean secure, + InetSocketAddress addr, + InetSocketAddress proxy) { + CacheKey key = new CacheKey(addr, proxy); + HttpConnection c = secure ? findConnection(key, sslPool) + : findConnection(key, plainPool); + //System.out.println ("getConnection returning: " + c); + return c; + } + + /** + * Returns the connection to the pool. + * + * @param conn + */ + synchronized void returnToPool(HttpConnection conn) { + if (conn instanceof PlainHttpConnection) { + putConnection(conn, plainPool); + } else { + putConnection(conn, sslPool); + } + addToExpiryList(conn); + //System.out.println("Return to pool: " + conn); + } + + private HttpConnection + findConnection(CacheKey key, + HashMap> pool) { + LinkedList l = pool.get(key); + if (l == null || l.size() == 0) { + return null; + } else { + HttpConnection c = l.removeFirst(); + removeFromExpiryList(c); + return c; + } + } + + /* called from cache cleaner only */ + private void + removeFromPool(HttpConnection c, + HashMap> pool) { + //System.out.println("cacheCleaner removing: " + c); + LinkedList l = pool.get(c.cacheKey()); + assert l != null; + boolean wasPresent = l.remove(c); + assert wasPresent; + } + + private void + putConnection(HttpConnection c, + HashMap> pool) { + CacheKey key = c.cacheKey(); + LinkedList l = pool.get(key); + if (l == null) { + l = new LinkedList<>(); + pool.put(key, l); + } + l.add(c); + } + + // only runs while entries exist in cache + + class CacheCleaner extends Thread { + + volatile boolean stopping; + + CacheCleaner() { + super(null, null, "HTTP-Cache-cleaner", 0, false); + setDaemon(true); + } + + synchronized boolean stopping() { + return stopping; + } + + synchronized void stopCleaner() { + stopping = true; + } + + @Override + public void run() { + while (!stopping()) { + try { + Thread.sleep(3000); + } catch (InterruptedException e) {} + cleanCache(); + } + } + } + + synchronized void removeFromExpiryList(HttpConnection c) { + if (c == null) { + return; + } + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry e = li.next(); + if (e.connection.equals(c)) { + li.remove(); + return; + } + } + if (expiryList.isEmpty()) { + cleaner.stopCleaner(); + } + } + + private void cleanCache() { + long now = System.currentTimeMillis() / 1000; + LinkedList closelist = new LinkedList<>(); + + synchronized (this) { + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry entry = li.next(); + if (entry.expiry <= now) { + li.remove(); + HttpConnection c = entry.connection; + closelist.add(c); + if (c instanceof PlainHttpConnection) { + removeFromPool(c, plainPool); + } else { + removeFromPool(c, sslPool); + } + } + } + } + for (HttpConnection c : closelist) { + //System.out.println ("KAC: closing " + c); + c.close(); + } + } + + private synchronized void addToExpiryList(HttpConnection conn) { + long now = System.currentTimeMillis() / 1000; + long then = now + KEEP_ALIVE; + + if (expiryList.isEmpty()) + cleaner = new CacheCleaner(); + + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry entry = li.next(); + + if (then > entry.expiry) { + li.previous(); + // insert here + li.add(new ExpiryEntry(conn, then)); + return; + } + } + // first element of list + expiryList.add(new ExpiryEntry(conn, then)); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java new file mode 100644 index 00000000000..1a95b667fdd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.io.IOException; +import java.net.CookieManager; +import java.util.List; +import java.util.Map; +import java.util.Set; + +class CookieFilter implements HeaderFilter { + + final HttpClientImpl client; + final CookieManager cookieMan; + + CookieFilter(HttpClientImpl client) { + this.client = client; + this.cookieMan = client.cookieManager().orElseThrow( + () -> new IllegalArgumentException("no cookie manager")); + } + + @Override + public void request(HttpRequestImpl r) throws IOException { + Map> userheaders, cookies; + userheaders = r.getUserHeaders().directMap(); + cookies = cookieMan.get(r.uri(), userheaders); + // add the returned cookies + HttpHeadersImpl systemHeaders = r.getSystemHeaders(); + Set keys = cookies.keySet(); + for (String hdrname : keys) { + List vals = cookies.get(hdrname); + for (String val : vals) { + systemHeaders.addHeader(hdrname, val); + } + } + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + HttpHeaders hdrs = r.headers(); + cookieMan.put(r.uri(), hdrs.map()); + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java new file mode 100644 index 00000000000..597b4c0b6a1 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.net.SocketPermission; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLPermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * One request/response exchange (handles 100/101 intermediate response also). + * depth field used to track number of times a new request is being sent + * for a given API request. If limit exceeded exception is thrown. + * + * Security check is performed here: + * - uses AccessControlContext captured at API level + * - checks for appropriate URLPermission for request + * - if permission allowed, grants equivalent SocketPermission to call + * - in case of direct HTTP proxy, checks additionally for access to proxy + * (CONNECT proxying uses its own Exchange, so check done there) + * + */ +class Exchange { + + final HttpRequestImpl request; + final HttpClientImpl client; + ExchangeImpl exchImpl; + HttpResponseImpl response; + final List permissions = new LinkedList<>(); + AccessControlContext acc; + boolean upgrading; // to HTTP/2 + + Exchange(HttpRequestImpl request) { + this.request = request; + this.upgrading = false; + this.client = request.client(); + } + + /* If different AccessControlContext to be used */ + Exchange(HttpRequestImpl request, AccessControlContext acc) { + this.request = request; + this.acc = acc; + this.upgrading = false; + this.client = request.client(); + } + + public HttpRequestImpl request() { + return request; + } + + public HttpResponseImpl response() throws IOException, InterruptedException { + response = responseImpl(null); + return response; + } + + public void cancel() { + if (exchImpl != null) + exchImpl.cancel(); + } + + public void h2Upgrade() { + upgrading = true; + request.setH2Upgrade(); + } + + static final SocketPermission[] SOCKET_ARRAY = new SocketPermission[0]; + + HttpResponseImpl responseImpl(HttpConnection connection) + throws IOException, InterruptedException + { + if (acc == null) { + acc = request.getAccessControlContext(); + } + SecurityException e = securityCheck(acc); + if (e != null) + throw e; + + if (permissions.size() > 0) { + try { + return AccessController.doPrivileged( + (PrivilegedExceptionAction)() -> + responseImpl0(connection), + null, + permissions.toArray(SOCKET_ARRAY)); + } catch (Throwable ee) { + if (ee instanceof PrivilegedActionException) { + ee = ee.getCause(); + } + if (ee instanceof IOException) + throw (IOException)ee; + else + throw new RuntimeException(ee); // TODO: fix + } + } else { + return responseImpl0(connection); + } + } + + HttpResponseImpl responseImpl0(HttpConnection connection) + throws IOException, InterruptedException + { + exchImpl = ExchangeImpl.get(this, connection); + if (request.expectContinue()) { + request.addSystemHeader("Expect", "100-Continue"); + exchImpl.sendHeadersOnly(); + HttpResponseImpl resp = exchImpl.getResponse(); + logResponse(resp); + if (resp.statusCode() != 100) { + return resp; + } + exchImpl.sendBody(); + return exchImpl.getResponse(); + } else { + exchImpl.sendRequest(); + HttpResponseImpl resp = exchImpl.getResponse(); + logResponse(resp); + return checkForUpgrade(resp, exchImpl); + } + } + + // Completed HttpResponse will be null if response succeeded + // will be a non null responseAsync if expect continue returns an error + + public CompletableFuture responseAsync(Void v) { + return responseAsyncImpl(null); + } + + CompletableFuture responseAsyncImpl(HttpConnection connection) { + if (acc == null) { + acc = request.getAccessControlContext(); + } + SecurityException e = securityCheck(acc); + if (e != null) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(e); + return cf; + } + if (permissions.size() > 0) { + return AccessController.doPrivileged( + (PrivilegedAction>)() -> + responseAsyncImpl0(connection), + null, + permissions.toArray(SOCKET_ARRAY)); + } else { + return responseAsyncImpl0(connection); + } + } + + CompletableFuture responseAsyncImpl0(HttpConnection connection) { + try { + exchImpl = ExchangeImpl.get(this, connection); + } catch (IOException | InterruptedException e) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(e); + return cf; + } + if (request.expectContinue()) { + request.addSystemHeader("Expect", "100-Continue"); + return exchImpl.sendHeadersAsync() + .thenCompose(exchImpl::getResponseAsync) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) + return cf; + if (rcode == 100) { + return exchImpl.sendBodyAsync() + .thenCompose(exchImpl::getResponseAsync) + .thenApply((r) -> { + logResponse(r); + return r; + }); + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } + }); + } else { + return exchImpl + .sendHeadersAsync() + .thenCompose((Void v) -> { + // send body and get response at same time + exchImpl.sendBodyAsync(); + return exchImpl.getResponseAsync(null); + }) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) { + return cf; + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } + }) + .thenApply((HttpResponseImpl response) -> { + this.response = response; + logResponse(response); + return response; + }); + } + } + + // if this response was received in reply to an upgrade + // then create the Http2Connection from the HttpConnection + // initialize it and wait for the real response on a newly created Stream + + private CompletableFuture + checkForUpgradeAsync(HttpResponseImpl resp, + ExchangeImpl ex) { + int rcode = resp.statusCode(); + if (upgrading && (rcode == 101)) { + Http1Exchange e = (Http1Exchange)ex; + // check for 101 switching protocols + return e.responseBodyAsync(HttpResponse.ignoreBody()) + .thenCompose((Void v) -> + Http2Connection.createAsync(e.connection(), + client.client2(), + this) + .thenCompose((Http2Connection c) -> { + Stream s = c.getStream(1); + exchImpl = s; + c.putConnection(); + return s.getResponseAsync(null); + }) + ); + } + return CompletableFuture.completedFuture(resp); + } + + private HttpResponseImpl checkForUpgrade(HttpResponseImpl resp, + ExchangeImpl ex) + throws IOException, InterruptedException + { + int rcode = resp.statusCode(); + if (upgrading && (rcode == 101)) { + Http1Exchange e = (Http1Exchange) ex; + // must get connection from Http1Exchange + e.responseBody(HttpResponse.ignoreBody(), false); + Http2Connection h2con = new Http2Connection(e.connection(), + client.client2(), + this); + h2con.putConnection(); + Stream s = h2con.getStream(1); + exchImpl = s; + return s.getResponse(); + } + return resp; + } + + + T responseBody(HttpResponse.BodyProcessor processor) { + try { + return exchImpl.responseBody(processor); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + + private void logResponse(HttpResponseImpl r) { + if (!Log.requests()) + return; + StringBuilder sb = new StringBuilder(); + String method = r.request().method(); + URI uri = r.uri(); + String uristring = uri == null ? "" : uri.toString(); + sb.append('(') + .append(method) + .append(" ") + .append(uristring) + .append(") ") + .append(Integer.toString(r.statusCode())); + Log.logResponse(sb.toString()); + } + + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return exchImpl.responseBodyAsync(processor); + } + + private URI getURIForSecurityCheck() { + URI u; + String method = request.method(); + InetSocketAddress authority = request.authority(); + URI uri = request.uri(); + + // CONNECT should be restricted at API level + if (method.equalsIgnoreCase("CONNECT")) { + try { + u = new URI("socket", + null, + authority.getHostString(), + authority.getPort(), + null, + null, + null); + } catch (URISyntaxException e) { + throw new InternalError(e); // shouldn't happen + } + } else { + u = uri; + } + return u; + } + + /** + * Do the security check and return any exception. + * Return null if no check needed or passes. + * + * Also adds any generated permissions to the "permissions" list. + */ + private SecurityException securityCheck(AccessControlContext acc) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return null; + } + + String method = request.method(); + HttpHeadersImpl userHeaders = request.getUserHeaders(); + URI u = getURIForSecurityCheck(); + URLPermission p = Utils.getPermission(u, method, userHeaders.directMap()); + + try { + assert acc != null; + sm.checkPermission(p, acc); + permissions.add(getSocketPermissionFor(u)); + } catch (SecurityException e) { + return e; + } + InetSocketAddress proxy = request.proxy(); + if (proxy != null) { + // may need additional check + if (!method.equals("CONNECT")) { + // a direct http proxy. Need to check access to proxy + try { + u = new URI("socket", null, proxy.getHostString(), + proxy.getPort(), null, null, null); + } catch (URISyntaxException e) { + throw new InternalError(e); // shouldn't happen + } + p = new URLPermission(u.toString(), "CONNECT"); + try { + sm.checkPermission(p, acc); + } catch (SecurityException e) { + permissions.clear(); + return e; + } + String sockperm = proxy.getHostString() + + ":" + Integer.toString(proxy.getPort()); + + permissions.add(new SocketPermission(sockperm, "connect,resolve")); + } + } + return null; + } + + private static SocketPermission getSocketPermissionFor(URI url) { + if (System.getSecurityManager() == null) + return null; + + StringBuilder sb = new StringBuilder(); + String host = url.getHost(); + sb.append(host); + int port = url.getPort(); + if (port == -1) { + String scheme = url.getScheme(); + if ("http".equals(scheme)) { + sb.append(":80"); + } else { // scheme must be https + sb.append(":443"); + } + } else { + sb.append(':') + .append(Integer.toString(port)); + } + String target = sb.toString(); + return new SocketPermission(target, "connect"); + } + + AccessControlContext getAccessControlContext() { + return acc; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java new file mode 100644 index 00000000000..bc3b6508d3c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import static java.net.http.HttpClient.Version.HTTP_1_1; + +/** + * Splits request so that headers and body can be sent separately with optional + * (multiple) responses in between (e.g. 100 Continue). Also request and + * response always sent/received in different calls. + * + * Synchronous and asynchronous versions of each method are provided. + * + * Separate implementations of this class exist for HTTP/1.1 and HTTP/2 + * Http1Exchange (HTTP/1.1) + * Stream (HTTP/2) + * + * These implementation classes are where work is allocated to threads. + */ +abstract class ExchangeImpl { + + final Exchange exchange; + + ExchangeImpl(Exchange e) { + this.exchange = e; + } + + /** + * Initiates a new exchange and assigns it to a connection if one exists + * already. connection usually null. + */ + static ExchangeImpl get(Exchange exchange, HttpConnection connection) + throws IOException, InterruptedException + { + HttpRequestImpl req = exchange.request(); + if (req.version() == HTTP_1_1) { + return new Http1Exchange(exchange, connection); + } else { + Http2ClientImpl c2 = exchange.request().client().client2(); // TODO: improve + HttpRequestImpl request = exchange.request(); + Http2Connection c = c2.getConnectionFor(request); + if (c == null) { + // no existing connection. Send request with HTTP 1 and then + // upgrade if successful + ExchangeImpl ex = new Http1Exchange(exchange, connection); + exchange.h2Upgrade(); + return ex; + } + return c.createStream(exchange); + } + } + + /* The following methods have separate HTTP/1.1 and HTTP/2 implementations */ + + /** + * Sends the request headers only. May block until all sent. + */ + abstract void sendHeadersOnly() throws IOException, InterruptedException; + + /** + * Gets response headers by blocking if necessary. This may be an + * intermediate response (like 101) or a final response 200 etc. + */ + abstract HttpResponseImpl getResponse() throws IOException; + + /** + * Sends a request body after request headers. + */ + abstract void sendBody() throws IOException, InterruptedException; + + /** + * Sends the entire request (headers and body) blocking. + */ + abstract void sendRequest() throws IOException, InterruptedException; + + /** + * Asynchronous version of sendHeaders(). + */ + abstract CompletableFuture sendHeadersAsync(); + + /** + * Asynchronous version of getResponse(). Requires void parameter for + * CompletableFuture chaining. + */ + abstract CompletableFuture getResponseAsync(Void v); + + /** + * Asynchronous version of sendBody(). + */ + abstract CompletableFuture sendBodyAsync(); + + /** + * Cancels a request. Not currently exposed through API. + */ + abstract void cancel(); + + /** + * Asynchronous version of sendRequest(). + */ + abstract CompletableFuture sendRequestAsync(); + + abstract T responseBody(HttpResponse.BodyProcessor processor) + throws IOException; + + /** + * Asynchronous version of responseBody(). + */ + abstract CompletableFuture + responseBodyAsync(HttpResponse.BodyProcessor processor); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java new file mode 100644 index 00000000000..ba8a07cf1cc --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; + +/** + * Wraps the supplied user ExecutorService. + * + * 1) when a Security manager set, the correct access control context + * is used to execute task + * + * 2) memory fence implemented + */ +class ExecutorWrapper { + + final ExecutorService userExecutor; // the actual executor service used + final Executor executor; + + public static ExecutorWrapper wrap(ExecutorService userExecutor) { + return new ExecutorWrapper(userExecutor); + } + + /** + * Returns a dummy ExecutorWrapper which uses the calling thread + */ + public static ExecutorWrapper callingThread() { + return new ExecutorWrapper(); + } + + private ExecutorWrapper(ExecutorService userExecutor) { + // used for executing in calling thread + this.userExecutor = userExecutor; + this.executor = userExecutor; + } + + private ExecutorWrapper() { + this.userExecutor = null; + this.executor = (Runnable command) -> { + command.run(); + }; + } + + public ExecutorService userExecutor() { + return userExecutor; + } + + public synchronized void synchronize() {} + + public void execute(Runnable r, Supplier ctxSupplier) { + synchronize(); + Runnable r1 = () -> { + try { + r.run(); + } catch (Throwable t) { + Log.logError(t); + } + }; + + if (ctxSupplier != null && System.getSecurityManager() != null) { + AccessControlContext acc = ctxSupplier.get(); + if (acc == null) { + throw new InternalError(); + } + AccessController.doPrivilegedWithCombiner( + (PrivilegedAction)() -> { + executor.execute(r1); // all throwables must be caught + return null; + }, acc); + } else { + executor.execute(r1); // all throwables must be caught + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java new file mode 100644 index 00000000000..cf67771331a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.util.LinkedList; +import java.util.List; + +class FilterFactory { + + final LinkedList> filterClasses = new LinkedList<>(); + + public void addFilter(Class type) { + filterClasses.add(type); + } + + List getFilterChain() { + List l = new LinkedList<>(); + for (Class clazz : filterClasses) { + try { + l.add(clazz.newInstance()); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } + } + return l; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java new file mode 100644 index 00000000000..d0fae94ada8 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.io.IOException; + +/** + * A header filter that can examine or modify, typically system headers for + * requests before they are sent, and responses before they are returned to the + * user. Some ability to resend requests is provided. + * + */ +interface HeaderFilter { + + void request(HttpRequestImpl r) throws IOException; + + /** + * Returns null if response ok to be given to user. Non null is a request + * that must be resent and its response given to user. If impl throws an + * exception that is returned to user instead. + */ + HttpRequestImpl response(HttpResponseImpl r) throws IOException; +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java new file mode 100644 index 00000000000..d4922d6a141 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.util.Iterator; +import java.util.Locale; +import java.util.NoSuchElementException; + +/* This is useful for the nightmare of parsing multi-part HTTP/RFC822 headers + * sensibly: + * From a String like: 'timeout=15, max=5' + * create an array of Strings: + * { {"timeout", "15"}, + * {"max", "5"} + * } + * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"' + * create one like (no quotes in literal): + * { {"basic", null}, + * {"realm", "FuzzFace"} + * {"foo", "Biz Bar Baz"} + * } + * keys are converted to lower case, vals are left as is.... + */ +class HeaderParser { + + /* table of key/val pairs */ + String raw; + String[][] tab; + int nkeys; + int asize = 10; // initial size of array is 10 + + public HeaderParser(String raw) { + this.raw = raw; + tab = new String[asize][2]; + parse(); + } + + private HeaderParser () { } + + /** + * Creates a new HeaderParser from this, whose keys (and corresponding + * values) range from "start" to "end-1" + */ + public HeaderParser subsequence(int start, int end) { + if (start == 0 && end == nkeys) { + return this; + } + if (start < 0 || start >= end || end > nkeys) + throw new IllegalArgumentException("invalid start or end"); + HeaderParser n = new HeaderParser(); + n.tab = new String [asize][2]; + n.asize = asize; + System.arraycopy (tab, start, n.tab, 0, (end-start)); + n.nkeys= (end-start); + return n; + } + + private void parse() { + + if (raw != null) { + raw = raw.trim(); + char[] ca = raw.toCharArray(); + int beg = 0, end = 0, i = 0; + boolean inKey = true; + boolean inQuote = false; + int len = ca.length; + while (end < len) { + char c = ca[end]; + if ((c == '=') && !inQuote) { // end of a key + tab[i][0] = new String(ca, beg, end-beg).toLowerCase(Locale.US); + inKey = false; + end++; + beg = end; + } else if (c == '\"') { + if (inQuote) { + tab[i++][1]= new String(ca, beg, end-beg); + inQuote=false; + do { + end++; + } while (end < len && (ca[end] == ' ' || ca[end] == ',')); + inKey=true; + beg=end; + } else { + inQuote=true; + end++; + beg=end; + } + } else if (c == ' ' || c == ',') { // end key/val, of whatever we're in + if (inQuote) { + end++; + continue; + } else if (inKey) { + tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase(Locale.US); + } else { + tab[i++][1] = (new String(ca, beg, end-beg)); + } + while (end < len && (ca[end] == ' ' || ca[end] == ',')) { + end++; + } + inKey = true; + beg = end; + } else { + end++; + } + if (i == asize) { + asize = asize * 2; + String[][] ntab = new String[asize][2]; + System.arraycopy (tab, 0, ntab, 0, tab.length); + tab = ntab; + } + } + // get last key/val, if any + if (--end > beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = (new String(ca, beg, end-beg)); + } else { + tab[i++][1] = (new String(ca, beg, end-beg+1)); + } + } else { + tab[i++][0] = (new String(ca, beg, end-beg+1)).toLowerCase(); + } + } else if (end == beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = String.valueOf(ca[end-1]); + } else { + tab[i++][1] = String.valueOf(ca[end]); + } + } else { + tab[i++][0] = String.valueOf(ca[end]).toLowerCase(); + } + } + nkeys=i; + } + } + + public String findKey(int i) { + if (i < 0 || i > asize) + return null; + return tab[i][0]; + } + + public String findValue(int i) { + if (i < 0 || i > asize) + return null; + return tab[i][1]; + } + + public String findValue(String key) { + return findValue(key, null); + } + + public String findValue(String k, String Default) { + if (k == null) + return Default; + k = k.toLowerCase(Locale.US); + for (int i = 0; i < asize; ++i) { + if (tab[i][0] == null) { + return Default; + } else if (k.equals(tab[i][0])) { + return tab[i][1]; + } + } + return Default; + } + + class ParserIterator implements Iterator { + int index; + boolean returnsValue; // or key + + ParserIterator (boolean returnValue) { + returnsValue = returnValue; + } + @Override + public boolean hasNext () { + return index= nkeys) + throw new NoSuchElementException(); + return tab[index++][returnsValue?1:0]; + } + } + + public Iterator keys () { + return new ParserIterator (false); + } + + public Iterator values () { + return new ParserIterator (true); + } + + @Override + public String toString () { + Iterator k = keys(); + StringBuilder sb = new StringBuilder(); + sb.append("{size=").append(asize).append(" nkeys=").append(nkeys) + .append(' '); + for (int i=0; k.hasNext(); i++) { + String key = k.next(); + String val = findValue (i); + if (val != null && "".equals (val)) { + val = null; + } + sb.append(" {").append(key).append(val == null ? "" : "," + val) + .append('}'); + if (k.hasNext()) { + sb.append (','); + } + } + sb.append (" }"); + return sb.toString(); + } + + public int findInt(String k, int Default) { + try { + return Integer.parseInt(findValue(k, String.valueOf(Default))); + } catch (Throwable t) { + return Default; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java new file mode 100644 index 00000000000..3266eada6c6 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.concurrent.CompletableFuture; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Encapsulates one HTTP/1.1 request/responseAsync exchange. + */ +class Http1Exchange extends ExchangeImpl { + + final HttpRequestImpl request; // main request + final List> operations; // used for cancel + final Http1Request requestAction; + volatile Http1Response response; + final HttpConnection connection; + final HttpClientImpl client; + final ExecutorWrapper executor; + + @Override + public String toString() { + return request.toString(); + } + + HttpRequestImpl request() { + return request; + } + + Http1Exchange(Exchange exchange, HttpConnection connection) + throws IOException + { + super(exchange); + this.request = exchange.request(); + this.client = request.client(); + this.executor = client.executorWrapper(); + this.operations = Collections.synchronizedList(new LinkedList<>()); + if (connection != null) { + this.connection = connection; + } else { + InetSocketAddress addr = getAddress(request); + this.connection = HttpConnection.getConnection(addr, request); + } + this.requestAction = new Http1Request(request, this.connection); + } + + private static InetSocketAddress getAddress(HttpRequestImpl req) { + URI uri = req.uri(); + if (uri == null) { + return req.authority(); + } + int port = uri.getPort(); + if (port == -1) { + if (uri.getScheme().equalsIgnoreCase("https")) { + port = 443; + } else { + port = 80; + } + } + String host = uri.getHost(); + if (req.proxy() == null) { + return new InetSocketAddress(host, port); + } else { + return InetSocketAddress.createUnresolved(host, port); + } + } + + HttpConnection connection() { + return connection; + } + + @Override + T responseBody(HttpResponse.BodyProcessor processor) + throws IOException + { + return responseBody(processor, true); + } + + T responseBody(HttpResponse.BodyProcessor processor, + boolean return2Cache) + throws IOException + { + try { + T body = response.readBody(processor, return2Cache); + return body; + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + @Override + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + CompletableFuture cf = new CompletableFuture<>(); + request.client() + .executorWrapper() + .execute(() -> { + try { + T body = responseBody(processor); + cf.complete(body); + } catch (Throwable e) { + cf.completeExceptionally(e); + } + }, + () -> response.response.getAccessControlContext()); // TODO: fix + return cf; + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + try { + if (!connection.connected()) { + connection.connect(); + } + requestAction.sendHeadersOnly(); + } catch (Throwable e) { + connection.close(); + throw e; + } + } + + @Override + void sendBody() throws IOException { + try { + requestAction.continueRequest(); + } catch (Throwable e) { + connection.close(); + throw e; + } + } + + @Override + HttpResponseImpl getResponse() throws IOException { + try { + response = new Http1Response(connection, this); + response.readHeaders(); + return response.response(); + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + @Override + void sendRequest() throws IOException, InterruptedException { + try { + if (!connection.connected()) { + connection.connect(); + } + requestAction.sendRequest(); + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + private void closeConnection() { + connection.close(); + } + + @Override + CompletableFuture sendHeadersAsync() { + if (!connection.connected()) { + CompletableFuture op = connection.connectAsync() + .thenCompose(this::sendHdrsAsyncImpl) + .whenComplete((Void b, Throwable t) -> { + if (t != null) + closeConnection(); + }); + operations.add(op); + return op; + } else { + return sendHdrsAsyncImpl(null); + } + } + + private CompletableFuture sendHdrsAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.sendHeadersOnly(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, + () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } + + /** + * Cancel checks to see if request and responseAsync finished already. + * If not it closes the connection and completes all pending operations + */ + @Override + synchronized void cancel() { + if (requestAction != null && requestAction.finished() + && response != null && response.finished()) { + return; + } + connection.close(); + IOException e = new IOException("Request cancelled"); + int count = 0; + for (CompletableFuture cf : operations) { + cf.completeExceptionally(e); + count++; + } + Log.logError("Http1Exchange.cancel: count=" + count); + } + + CompletableFuture getResponseAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + try { + response = new Http1Response(connection, Http1Exchange.this); + response.readHeaders(); + cf.complete(response.response()); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + } + + @Override + CompletableFuture getResponseAsync(Void v) { + CompletableFuture cf = + connection.whenReceivingResponse() + .thenCompose(this::getResponseAsyncImpl); + + operations.add(cf); + return cf; + } + + @Override + CompletableFuture sendBodyAsync() { + final CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.continueRequest(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } + + @Override + CompletableFuture sendRequestAsync() { + CompletableFuture op; + if (!connection.connected()) { + op = connection.connectAsync() + .thenCompose(this::sendRequestAsyncImpl) + .whenComplete((Void v, Throwable t) -> { + if (t != null) { + closeConnection(); + } + }); + } else { + op = sendRequestAsyncImpl(null); + } + operations.add(op); + return op; + } + + CompletableFuture sendRequestAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.sendRequest(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java new file mode 100644 index 00000000000..f0da88b3b5c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.function.LongConsumer; +import static java.nio.charset.StandardCharsets.US_ASCII; + +/** + * A HTTP/1.1 request. + * + * send() -> Writes the request + body to the given channel, in one blocking + * operation. + */ +class Http1Request { + + final HttpRequestImpl request; + final HttpConnection chan; + // Multiple buffers are used to hold different parts of request + // See line 206 and below for description + final ByteBuffer[] buffers; + final HttpRequest.BodyProcessor requestProc; + final HttpHeadersImpl userHeaders, systemHeaders; + final LongConsumer flowController; + boolean streaming; + long contentLength; + + Http1Request(HttpRequestImpl request, HttpConnection connection) + throws IOException + { + this.request = request; + this.chan = connection; + buffers = new ByteBuffer[5]; // TODO: check + this.requestProc = request.requestProcessor(); + this.userHeaders = request.getUserHeaders(); + this.systemHeaders = request.getSystemHeaders(); + this.flowController = this::dummy; + } + + private void logHeaders() throws IOException { + StringBuilder sb = new StringBuilder(256); + sb.append("REQUEST HEADERS:\r\n"); + collectHeaders1(sb, request, systemHeaders); + collectHeaders1(sb, request, userHeaders); + Log.logHeaders(sb.toString()); + } + + private void dummy(long x) { + // not used in this class + } + + private void collectHeaders0() throws IOException { + if (Log.headers()) { + logHeaders(); + } + StringBuilder sb = new StringBuilder(256); + collectHeaders1(sb, request, systemHeaders); + collectHeaders1(sb, request, userHeaders); + sb.append("\r\n"); + String headers = sb.toString(); + buffers[1] = ByteBuffer.wrap(headers.getBytes(StandardCharsets.US_ASCII)); + } + + private void collectHeaders1(StringBuilder sb, + HttpRequestImpl request, + HttpHeadersImpl headers) + throws IOException + { + Map> h = headers.directMap(); + Set>> entries = h.entrySet(); + + for (Map.Entry> entry : entries) { + String key = entry.getKey(); + sb.append(key).append(": "); + List values = entry.getValue(); + int num = values.size(); + for (String value : values) { + sb.append(value); + if (--num > 0) { + sb.append(','); + } + } + sb.append("\r\n"); + } + } + + private static final int BUFSIZE = 64 * 1024; // TODO: configurable? + + private String getPathAndQuery(URI uri) { + String path = uri.getPath(); + String query = uri.getQuery(); + if (path == null || path.equals("")) { + path = "/"; + } + if (query == null) { + query = ""; + } + if (query.equals("")) { + return path; + } else { + return path + "?" + query; + } + } + + private String authorityString(InetSocketAddress addr) { + return addr.getHostString() + ":" + addr.getPort(); + } + + private String requestURI() { + URI uri = request.uri(); + String method = request.method(); + + if ((request.proxy() == null && !method.equals("CONNECT")) + || request.isWebSocket()) { + return getPathAndQuery(uri); + } + if (request.secure()) { + if (request.method().equals("CONNECT")) { + // use authority for connect itself + return authorityString(request.authority()); + } else { + // requests over tunnel do not require full URL + return getPathAndQuery(uri); + } + } + return uri == null? authorityString(request.authority()) : uri.toString(); + } + + void sendHeadersOnly() throws IOException { + collectHeaders(); + chan.write(buffers, 0, 2); + } + + void sendRequest() throws IOException { + collectHeaders(); + if (contentLength == 0) { + chan.write(buffers, 0, 2); + } else if (contentLength > 0) { + writeFixedContent(true); + } else { + writeStreamedContent(true); + } + setFinished(); + } + + private boolean finished; + + synchronized boolean finished() { + return finished; + } + + synchronized void setFinished() { + finished = true; + } + + private void collectHeaders() throws IOException { + if (Log.requests() && request != null) { + Log.logRequest(request.toString()); + } + String uriString = requestURI(); + StringBuilder sb = new StringBuilder(64); + sb.append(request.method()) + .append(' ') + .append(uriString) + .append(" HTTP/1.1\r\n"); + String cmd = sb.toString(); + + buffers[0] = ByteBuffer.wrap(cmd.getBytes(StandardCharsets.US_ASCII)); + URI uri = request.uri(); + if (uri != null) { + systemHeaders.setHeader("Host", uri.getHost()); + } + if (request == null) { + // this is not a user request. No content + contentLength = 0; + } else { + contentLength = requestProc.onRequestStart(request, flowController); + } + + if (contentLength == 0) { + systemHeaders.setHeader("Content-Length", "0"); + collectHeaders0(); + } else if (contentLength > 0) { + /* [0] request line [1] headers [2] body */ + systemHeaders.setHeader("Content-Length", + Integer.toString((int) contentLength)); + streaming = false; + collectHeaders0(); + buffers[2] = chan.getBuffer(); + } else { + /* Chunked: + * + * [0] request line [1] headers [2] chunk header [3] chunk data [4] + * final chunk header and trailing CRLF of previous chunks + * + * 2,3,4 used repeatedly */ + streaming = true; + systemHeaders.setHeader("Transfer-encoding", "chunked"); + collectHeaders0(); + buffers[3] = chan.getBuffer(); + } + } + + // The following two methods used by Http1Exchange to handle expect continue + + void continueRequest() throws IOException { + if (streaming) { + writeStreamedContent(false); + } else { + writeFixedContent(false); + } + setFinished(); + } + + /* Entire request is sent, or just body only */ + private void writeStreamedContent(boolean includeHeaders) + throws IOException + { + if (requestProc instanceof HttpRequest.BodyProcessor) { + HttpRequest.BodyProcessor pullproc = requestProc; + int startbuf, nbufs; + + if (includeHeaders) { + startbuf = 0; + nbufs = 5; + } else { + startbuf = 2; + nbufs = 3; + } + try { + // TODO: currently each write goes out as one chunk + // TODO: should be collecting data and buffer it. + + buffers[3].clear(); + boolean done = pullproc.onRequestBodyChunk(buffers[3]); + int chunklen = buffers[3].position(); + buffers[2] = getHeader(chunklen); + buffers[3].flip(); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, startbuf, nbufs); + while (!done) { + buffers[3].clear(); + done = pullproc.onRequestBodyChunk(buffers[3]); + if (done) + break; + buffers[3].flip(); + chunklen = buffers[3].remaining(); + buffers[2] = getHeader(chunklen); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, 2, 3); + } + buffers[3] = EMPTY_CHUNK_HEADER(); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, 3, 2); + } catch (IOException e) { + requestProc.onRequestError(e); + throw e; + } + } + } + /* Entire request is sent, or just body only */ + private void writeFixedContent(boolean includeHeaders) + throws IOException + { + try { + int startbuf, nbufs; + + if (contentLength == 0) { + return; + } + if (includeHeaders) { + startbuf = 0; + nbufs = 3; + } else { + startbuf = 2; + nbufs = 1; + buffers[0].clear().flip(); + buffers[1].clear().flip(); + } + buffers[2] = chan.getBuffer(); + if (requestProc instanceof HttpRequest.BodyProcessor) { + HttpRequest.BodyProcessor pullproc = requestProc; + + boolean done = pullproc.onRequestBodyChunk(buffers[2]); + buffers[2].flip(); + long headersLength = buffers[0].remaining() + buffers[1].remaining(); + long contentWritten = buffers[2].remaining(); + chan.checkWrite(headersLength + contentWritten, + buffers, + startbuf, + nbufs); + while (!done) { + buffers[2].clear(); + done = pullproc.onRequestBodyChunk(buffers[2]); + buffers[2].flip(); + long len = buffers[2].remaining(); + if (contentWritten + len > contentLength) { + break; + } + chan.checkWrite(len, buffers[2]); + contentWritten += len; + } + if (contentWritten != contentLength) { + throw new IOException("wrong content length"); + } + } + } catch (IOException e) { + requestProc.onRequestError(e); + throw e; + } + } + + private static final byte[] CRLF = {'\r', '\n'}; + private static final byte[] EMPTY_CHUNK_BYTES = {'0', '\r', '\n'}; + + private ByteBuffer CRLF_BUFFER() { + return ByteBuffer.wrap(CRLF); + } + + private ByteBuffer EMPTY_CHUNK_HEADER() { + return ByteBuffer.wrap(EMPTY_CHUNK_BYTES); + } + + /* Returns a header for a particular chunk size */ + private static ByteBuffer getHeader(int size){ + String hexStr = Integer.toHexString(size); + byte[] hexBytes = hexStr.getBytes(US_ASCII); + byte[] header = new byte[hexStr.length()+2]; + System.arraycopy(hexBytes, 0, header, 0, hexBytes.length); + header[hexBytes.length] = CRLF[0]; + header[hexBytes.length+1] = CRLF[1]; + return ByteBuffer.wrap(header); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java new file mode 100644 index 00000000000..6fad37b6b8f --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.LongConsumer; +import static java.net.http.HttpClient.Version.HTTP_1_1; + +/** + * Handles a HTTP/1.1 response in two blocking calls. readHeaders() and + * readBody(). There can be more than one of these per Http exchange. + */ +class Http1Response { + + private ResponseContent content; + private final HttpRequestImpl request; + HttpResponseImpl response; + private final HttpConnection connection; + private ResponseHeaders headers; + private int responseCode; + private ByteBuffer buffer; // same buffer used for reading status line and headers + private final Http1Exchange exchange; + private final boolean redirecting; // redirecting + private boolean return2Cache; // return connection to cache when finished + + Http1Response(HttpConnection conn, Http1Exchange exchange) { + this.request = exchange.request(); + this.exchange = exchange; + this.connection = conn; + this.redirecting = false; + buffer = connection.getRemaining(); + } + + // called when the initial read should come from a buffer left + // over from a previous response. + void setBuffer(ByteBuffer buffer) { + this.buffer = buffer; + } + + @SuppressWarnings("unchecked") + public void readHeaders() throws IOException { + String statusline = readStatusLine(); + if (statusline == null) { + if (Log.errors()) { + Log.logError("Connection closed. Retry"); + } + connection.close(); + // connection was closed + throw new IOException("Connection closed"); + } + if (!statusline.startsWith("HTTP/1.")) { + throw new IOException("Invalid status line: " + statusline); + } + char c = statusline.charAt(7); + responseCode = Integer.parseInt(statusline.substring(9, 12)); + + headers = new ResponseHeaders(connection, buffer); + headers.initHeaders(); + if (Log.headers()) { + logHeaders(headers); + } + response = new HttpResponseImpl(responseCode, + exchange.exchange, + headers, + null, + connection.sslParameters(), + HTTP_1_1, + connection); + } + + private boolean finished; + + synchronized void completed() { + finished = true; + } + + synchronized boolean finished() { + return finished; + } + + // Blocking flow controller implementation. Only works when a + // thread is dedicated to reading response body + + static class FlowController implements LongConsumer { + long window ; + + @Override + public synchronized void accept(long value) { + window += value; + notifyAll(); + } + + public synchronized void request(long value) throws InterruptedException { + while (window < value) { + wait(); + } + window -= value; + } + } + + FlowController flowController; + + int fixupContentLen(int clen) { + if (request.method().equalsIgnoreCase("HEAD")) { + return 0; + } + if (clen == -1) { + if (headers.firstValue("Transfer-encoding").orElse("") + .equalsIgnoreCase("chunked")) { + return -1; + } + return 0; + } + return clen; + } + + private void returnBuffer(ByteBuffer buf) { + // not currently used, but will be when we change SSL to use fixed + // sized buffers and a single buffer pool for HttpClientImpl + } + + @SuppressWarnings("unchecked") + public T readBody(java.net.http.HttpResponse.BodyProcessor p, + boolean return2Cache) + throws IOException + { + T body = null; // TODO: check null case below + this.return2Cache = return2Cache; + final java.net.http.HttpResponse.BodyProcessor pusher = p; + + int clen0 = headers.getContentLength(); + final int clen = fixupContentLen(clen0); + + flowController = new FlowController(); + + body = pusher.onResponseBodyStart(clen, headers, flowController); + + ExecutorWrapper executor; + if (body == null) { + executor = ExecutorWrapper.callingThread(); + } else { + executor = request.client().executorWrapper(); + } + + final ResponseHeaders h = headers; + if (body == null) { + content = new ResponseContent(connection, + clen, + h, + pusher, + flowController); + content.pushBody(headers.getResidue()); + body = pusher.onResponseComplete(); + completed(); + onFinished(); + return body; + } else { + executor.execute(() -> { + try { + content = new ResponseContent(connection, + clen, + h, + pusher, + flowController); + content.pushBody(headers.getResidue()); + pusher.onResponseComplete(); + completed(); + onFinished(); + } catch (Throwable e) { + pusher.onResponseError(e); + } + }, + () -> response.getAccessControlContext()); + } + return body; + } + + private void onFinished() { + connection.buffer = content.getResidue(); + if (return2Cache) { + connection.returnToCache(headers); + } + } + + private void logHeaders(ResponseHeaders headers) { + Map> h = headers.mapInternal(); + Set keys = h.keySet(); + Set>> entries = h.entrySet(); + for (Map.Entry> entry : entries) { + String key = entry.getKey(); + StringBuilder sb = new StringBuilder(); + sb.append(key).append(": "); + List values = entry.getValue(); + if (values != null) { + for (String value : values) { + sb.append(value).append(' '); + } + } + Log.logHeaders(sb.toString()); + } + } + + HttpResponseImpl response() { + return response; + } + + boolean redirecting() { + return redirecting; + } + + HttpHeaders responseHeaders() { + return headers; + } + + int responseCode() { + return responseCode; + } + + static final char CR = '\r'; + static final char LF = '\n'; + + private ByteBuffer getBuffer() throws IOException { + if (buffer == null || !buffer.hasRemaining()) { + buffer = connection.read(); + } + return buffer; + } + + ByteBuffer buffer() { + return buffer; + } + + String readStatusLine() throws IOException { + boolean cr = false; + StringBuilder statusLine = new StringBuilder(128); + ByteBuffer b; + while ((b = getBuffer()) != null) { + byte[] buf = b.array(); + int offset = b.position(); + int len = b.limit() - offset; + + for (int i = 0; i < len; i++) { + char c = (char) buf[i+offset]; + + if (cr) { + if (c == LF) { + b.position(i + 1 + offset); + return statusLine.toString(); + } else { + throw new IOException("invalid status line"); + } + } + if (c == CR) { + cr = true; + } else { + statusLine.append(c); + } + } + // unlikely, but possible, that multiple reads required + b.position(b.limit()); + } + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java new file mode 100644 index 00000000000..4491168225b --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +class Http2ClientImpl { + Http2ClientImpl(HttpClientImpl t) {} + String getSettingsString() {return "";} + void debugPrint() {} + Http2Connection getConnectionFor(HttpRequestImpl r) { + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java new file mode 100644 index 00000000000..3f60c4f805e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.net.URI; +import static java.net.http.Utils.BUFSIZE; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import java.nio.channels.Selector; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.*; +import java.security.NoSuchAlgorithmException; +import java.util.ListIterator; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +class Http2Connection { + static CompletableFuture createAsync( + HttpConnection connection, Http2ClientImpl client2, Exchange exchange) { + return null; + } + + Http2Connection(HttpConnection connection, Http2ClientImpl client2, + Exchange exchange) throws IOException, InterruptedException { + } + + Stream getStream(int i) {return null;} + Stream createStream(Exchange ex) {return null;} + void putConnection() {} +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java new file mode 100644 index 00000000000..d0989f399cb --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.InetSocketAddress; +import java.net.NetPermission; +import java.net.ProxySelector; +import java.net.URI; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +/** + * A container for configuration information common to multiple {@link + * HttpRequest}s. All requests are associated with, and created from a {@code + * HttpClient}. + * + *

    {@code HttpClient}s are immutable and created from a builder returned + * from {@link HttpClient#create()}. Request builders that are associated with + * an application created client, are created by calling {@link #request(URI) }. + * It is also possible to create a request builder directly which is associated + * with the default {@code HttpClient} by calling {@link + * HttpRequest#create(URI)}. + * + *

    The HTTP API functions asynchronously (using {@link + * java.util.concurrent.CompletableFuture}) and also in a simple synchronous + * mode, where all work may be done on the calling thread. In asynchronous mode, + * work is done on the threads supplied by the client's {@link + * java.util.concurrent.ExecutorService}. + * + *

    The default {@code HttpClient} is + * used whenever a request is created without specifying a client explicitly + * (by calling {@link HttpRequest#create(java.net.URI) HttpRequest.create}). + * There is only one static instance of this {@code HttpClient}. A reference to + * the default client can be obtained by calling {@link #getDefault() }. If a + * security manager is set, then a permission is required for this. + * + *

    See {@link HttpRequest} for examples of usage of this API. + * + * @since 9 + */ +public abstract class HttpClient { + + HttpClient() {} + + private static HttpClient defaultClient; + + /** + * Creates a new {@code HttpClient} builder. + * + * @return a {@code HttpClient.Builder} + */ + public static Builder create() { + return new HttpClientBuilderImpl(); + } + + //public abstract void debugPrint(); + + /** + * Returns the default {@code HttpClient} that is used when a {@link + * HttpRequest} is created without specifying a client. If a security + * manager is set, then its {@code checkPermission} method is called with a + * {@link java.net.NetPermission} specifying the name "getDefaultHttpClient". + * If the caller does not possess this permission a {@code SecurityException} + * is thrown. + * + * @implNote Code running under a security manager can avoid the security + * manager check by creating a {@code HttpClient} explicitly. + * + * @return the default {@code HttpClient} + * @throws SecurityException if the caller does not have the required + * permission + */ + public synchronized static HttpClient getDefault() { + Utils.checkNetPermission("getDefaultHttpClient"); + if (defaultClient == null) { + Builder b = create(); + defaultClient = b.executorService(Executors.newCachedThreadPool()) + .build(); + } + return defaultClient; + } + + /** + * Creates a {@code HttpRequest} builder associated with this client. + * + * @return a new builder + */ + public abstract HttpRequest.Builder request(); + + /** + * Creates a {@code HttpRequest} builder associated with this client and + * using the given request URI. + * + * @param uri the request URI + * @return a new builder + */ + public abstract HttpRequest.Builder request(URI uri); + + /** + * A builder of immutable {@link HttpClient}s. {@code HttpClient.Builder}s + * are created by calling {@link HttpClient#create()}. + * + *

    Each of the setter methods in this class modifies the state of the + * builder and returns this (ie. the same instance). The methods are + * not synchronized and should not be called from multiple threads without + * external synchronization. + * + *

    {@link #build() } returns a new {@code HttpClient} each time it is + * called. + * + * @since 9 + */ + public abstract static class Builder { + + Builder() {} + + /** + * Sets a cookie manager. + * + * @param manager the CookieManager + * @return this builder + * @throws NullPointerException if {@code manager} is null + */ + public abstract Builder cookieManager(CookieManager manager); + + /** + * Sets an SSLContext. If a security manager is set, then the caller + * must have the {@link java.net.NetPermission NetPermission} + * ("setSSLContext") + * + *

    The effect of not calling this method, is that a default {@link + * javax.net.ssl.SSLContext} is used, which is normally adequate for + * client applications that do not need to specify protocols, or require + * client authentication. + * + * @param sslContext the SSLContext + * @return this builder + * @throws NullPointerException if {@code sslContext} is null + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission + */ + public abstract Builder sslContext(SSLContext sslContext); + + /** + * Sets an SSLParameters. If this method is not called, then a default + * set of parameters are used. The contents of the given object are + * copied. Some parameters which are used internally by the HTTP protocol + * implementation (such as application protocol list) should not be set + * by callers, as they are ignored. + * + * @param sslParameters the SSLParameters + * @return this builder + * @throws NullPointerException if {@code sslParameters} is null + */ + public abstract Builder sslParameters(SSLParameters sslParameters); + + /** + * Sets the ExecutorService to be used for sending and receiving + * asynchronous requests. If this method is not called, a default + * executor service is set, which is the one returned from {@link + * java.util.concurrent.Executors#newCachedThreadPool() + * Executors.newCachedThreadPool}. + * + * @param s the ExecutorService + * @return this builder + * @throws NullPointerException if {@code s} is null + */ + public abstract Builder executorService(ExecutorService s); + + /** + * Specifies whether requests will automatically follow redirects issued + * by the server. This setting can be overridden on each request. The + * default value for this setting is {@link Redirect#NEVER NEVER} + * + * @param policy the redirection policy + * @return this builder + * @throws NullPointerException if {@code policy} is null + */ + public abstract Builder followRedirects(Redirect policy); + + /** + * Requests a specific HTTP protocol version where possible. If not set, + * the version defaults to {@link HttpClient.Version#HTTP_1_1}. If + * {@link HttpClient.Version#HTTP_2} is set, then each request will + * attempt to upgrade to HTTP/2. If the upgrade succeeds, then the + * response to this request will use HTTP/2 and all subsequent requests + * and responses to the same + * origin server + * will use HTTP/2. If the upgrade fails, then the response will be + * handled using HTTP/1.1 + * + *

    This setting can be over-ridden per request. + * + * @param version the requested HTTP protocol version + * @return this builder + * @throws NullPointerException if {@code version} is null + */ + public abstract Builder version(HttpClient.Version version); + + /** + * Sets the default priority for any HTTP/2 requests sent from this + * client. The value provided must be between {@code 1} and {@code 255}. + * + * @param priority the priority weighting + * @return this builder + * @throws IllegalArgumentException if the given priority is out of range + */ + public abstract Builder priority(int priority); + + /** + * Enables pipelining mode for HTTP/1.1 requests sent through this + * client. When pipelining is enabled requests to the same destination + * are sent over existing TCP connections that may already have requests + * outstanding. This reduces the number of connections, but may have + * a performance impact since responses must be delivered in the same + * order that they were sent. By default, pipelining is disabled. + * + * @param enable {@code true} enables pipelining + * @return this builder + * @throws UnsupportedOperationException if pipelining mode is not + * supported by this implementation + */ + public abstract Builder pipelining(boolean enable); + + /** + * Sets a {@link java.net.ProxySelector} for this client. If no selector + * is set, then no proxies are used. If a {@code null} parameter is + * given then the system wide default proxy selector is used. + * + * @implNote {@link java.net.ProxySelector#of(InetSocketAddress)} + * provides a ProxySelector which uses one proxy for all requests. + * + * @param selector the ProxySelector + * @return this builder + */ + public abstract Builder proxy(ProxySelector selector); + + /** + * Sets an authenticator to use for HTTP authentication. + * + * @param a the Authenticator + * @return this builder + */ + public abstract Builder authenticator(Authenticator a); + + /** + * Returns a {@link HttpClient} built from the current state of this + * builder. + * + * @return this builder + */ + public abstract HttpClient build(); + } + + + /** + * Returns an {@code Optional} which contains this client's {@link + * CookieManager}. If no CookieManager was set in this client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's CookieManager + */ + public abstract Optional cookieManager(); + + /** + * Returns the follow-redirects setting for this client. The default value + * for this setting is {@link HttpClient.Redirect#NEVER} + * + * @return this client's follow redirects setting + */ + public abstract Redirect followRedirects(); + + /** + * Returns an {@code Optional} containing the ProxySelector for this client. + * If no proxy is set then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's proxy selector + */ + public abstract Optional proxy(); + + /** + * Returns the SSLContext, if one was set on this client. If a security + * manager is set then then caller must then the caller must have the + * {@link java.net.NetPermission NetPermission}("getSSLContext") permission. + * If no SSLContext was set, then the default context is returned. + * + * @return this client's SSLContext + */ + public abstract SSLContext sslContext(); + + /** + * Returns an {@code Optional} containing the {@link SSLParameters} set on + * this client. If no {@code SSLParameters} were set in the client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's SSLParameters + */ + public abstract Optional sslParameters(); + + /** + * Returns an {@code Optional} containing the {@link Authenticator} set on + * this client. If no {@code Authenticator} was set in the client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's Authenticator + */ + public abstract Optional authenticator(); + + /** + * Returns the HTTP protocol version requested for this client. The default + * value is {@link HttpClient.Version#HTTP_1_1} + * + * @return the HTTP protocol version requested + */ + public abstract HttpClient.Version version(); + + /** + * Returns whether this client supports HTTP/1.1 pipelining. + * + * @return whether pipelining allowed + */ + public abstract boolean pipelining(); + + /** + * Returns the {@code ExecutorService} set on this client. If an {@code + * ExecutorService} was not set on the client's builder, then a default + * object is returned. The default ExecutorService is created independently + * for each client. + * + * @return this client's ExecutorService + */ + public abstract ExecutorService executorService(); + + /** + * The HTTP protocol version. + * + * @since 9 + */ + public static enum Version { + + /** + * HTTP version 1.1 + */ + HTTP_1_1, + + /** + * HTTP version 2 + */ + HTTP_2 + } + + /** + * Defines automatic redirection policy. This is checked whenever a 3XX + * response code is received. If redirection does not happen automatically + * then the response is returned to the user, where it can be handled + * manually. + * + *

    {@code Redirect} policy is set via the {@link + * HttpClient.Builder#followRedirects(HttpClient.Redirect)} method. + * + * @since 9 + */ + public static enum Redirect { + + /** + * Never redirect. + */ + NEVER, + + /** + * Always redirect. + */ + ALWAYS, + + /** + * Redirect to same protocol only. Redirection may occur from HTTP URLs + * to other HTTP URLs, and from HTTPS URLs to other HTTPS URLs. + */ + SAME_PROTOCOL, + + /** + * Redirect always except from HTTPS URLs to HTTP URLs. + */ + SECURE + } + +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java new file mode 100644 index 00000000000..c93025d477a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +class HttpClientBuilderImpl extends HttpClient.Builder { + + CookieManager cookieManager; + HttpClient.Redirect followRedirects; + ProxySelector proxy; + Authenticator authenticator; + HttpClient.Version version = HttpClient.Version.HTTP_1_1; + ExecutorService executor; + // Security parameters + SSLContext sslContext; + SSLParameters sslParams; + int priority = -1; + + @Override + public HttpClientBuilderImpl cookieManager(CookieManager manager) { + Objects.requireNonNull(manager); + this.cookieManager = manager; + return this; + } + + + @Override + public HttpClientBuilderImpl sslContext(SSLContext sslContext) { + Objects.requireNonNull(sslContext); + Utils.checkNetPermission("setSSLContext"); + this.sslContext = sslContext; + return this; + } + + + @Override + public HttpClientBuilderImpl sslParameters(SSLParameters sslParameters) { + Objects.requireNonNull(sslParameters); + this.sslParams = sslParameters; + return this; + } + + + @Override + public HttpClientBuilderImpl executorService(ExecutorService s) { + Objects.requireNonNull(s); + this.executor = s; + return this; + } + + + @Override + public HttpClientBuilderImpl followRedirects(HttpClient.Redirect policy) { + Objects.requireNonNull(policy); + this.followRedirects = policy; + return this; + } + + + @Override + public HttpClientBuilderImpl version(HttpClient.Version version) { + Objects.requireNonNull(version); + this.version = version; + return this; + } + + + @Override + public HttpClientBuilderImpl priority(int priority) { + if (priority < 1 || priority > 255) { + throw new IllegalArgumentException("priority must be between 1 and 255"); + } + this.priority = priority; + return this; + } + + + @Override + public HttpClientBuilderImpl pipelining(boolean enable) { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } + + + @Override + public HttpClientBuilderImpl proxy(ProxySelector proxy) { + Objects.requireNonNull(proxy); + this.proxy = proxy; + return this; + } + + + @Override + public HttpClientBuilderImpl authenticator(Authenticator a) { + Objects.requireNonNull(a); + this.authenticator = a; + return this; + } + + @Override + public HttpClient build() { + return HttpClientImpl.create(this); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java new file mode 100644 index 00000000000..e7e53bd6346 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.net.URI; +import static java.net.http.Utils.BUFSIZE; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import java.nio.channels.Selector; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.security.NoSuchAlgorithmException; +import java.util.ListIterator; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +/** + * Client implementation. Contains all configuration information and also + * the selector manager thread which allows async events to be registered + * and delivered when they occur. See AsyncEvent. + */ +class HttpClientImpl extends HttpClient implements BufferHandler { + + private final CookieManager cookieManager; + private final Redirect followRedirects; + private final ProxySelector proxySelector; + private final Authenticator authenticator; + private final Version version; + private boolean pipelining = false; + private final ConnectionPool connections; + private final ExecutorWrapper executor; + // Security parameters + private final SSLContext sslContext; + private final SSLParameters sslParams; + private final SelectorManager selmgr; + private final FilterFactory filters; + private final Http2ClientImpl client2; + private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); + private final LinkedList timeouts; + + //@Override + void debugPrint() { + selmgr.debugPrint(); + client2.debugPrint(); + } + + public static HttpClientImpl create(HttpClientBuilderImpl builder) { + HttpClientImpl impl = new HttpClientImpl(builder); + impl.start(); + return impl; + } + + private HttpClientImpl(HttpClientBuilderImpl builder) { + if (builder.sslContext == null) { + try { + sslContext = SSLContext.getDefault(); + } catch (NoSuchAlgorithmException ex) { + throw new InternalError(ex); + } + } else { + sslContext = builder.sslContext; + } + ExecutorService ex = builder.executor; + if (ex == null) { + ex = Executors.newCachedThreadPool((r) -> { + Thread t = defaultFactory.newThread(r); + t.setDaemon(true); + return t; + }); + } else { + ex = builder.executor; + } + client2 = new Http2ClientImpl(this); + executor = ExecutorWrapper.wrap(ex); + cookieManager = builder.cookieManager; + followRedirects = builder.followRedirects == null ? + Redirect.NEVER : builder.followRedirects; + this.proxySelector = builder.proxy; + authenticator = builder.authenticator; + version = builder.version; + sslParams = builder.sslParams; + connections = new ConnectionPool(); + connections.start(); + timeouts = new LinkedList<>(); + try { + selmgr = new SelectorManager(); + } catch (IOException e) { + // unlikely + throw new InternalError(e); + } + selmgr.setDaemon(true); + selmgr.setName("HttpSelector"); + filters = new FilterFactory(); + initFilters(); + } + + private void start() { + selmgr.start(); + } + + /** + * Wait for activity on given exchange (assuming blocking = false). + * It's a no-op if blocking = true. In particular, the following occurs + * in the SelectorManager thread. + * + * 1) mark the connection non-blocking + * 2) add to selector + * 3) If selector fires for this exchange then + * 4) - mark connection as blocking + * 5) - call AsyncEvent.handle() + * + * If exchange needs to block again, then call registerEvent() again + */ + void registerEvent(AsyncEvent exchange) throws IOException { + selmgr.register(exchange); + } + + Http2ClientImpl client2() { + return client2; + } + + LinkedList freelist = new LinkedList<>(); + + @Override + public synchronized ByteBuffer getBuffer() { + if (freelist.isEmpty()) { + return ByteBuffer.allocate(BUFSIZE); + } + return freelist.removeFirst(); + } + + @Override + public synchronized void returnBuffer(ByteBuffer buffer) { + buffer.clear(); + freelist.add(buffer); + } + + + // Main loop for this client's selector + + class SelectorManager extends Thread { + + final Selector selector; + boolean closed; + + final List readyList; + final List registrations; + + List debugList; + + SelectorManager() throws IOException { + readyList = new LinkedList<>(); + registrations = new LinkedList<>(); + debugList = new LinkedList<>(); + selector = Selector.open(); + } + + // This returns immediately. So caller not allowed to send/receive + // on connection. + + synchronized void register(AsyncEvent e) throws IOException { + registrations.add(e); + selector.wakeup(); + } + + void wakeupSelector() { + selector.wakeup(); + } + + synchronized void shutdown() { + closed = true; + try { + selector.close(); + } catch (IOException e) {} + } + + private List copy(List list) { + LinkedList c = new LinkedList<>(); + for (AsyncEvent e : list) { + c.add(e); + } + return c; + } + + synchronized void debugPrint() { + System.err.println("Selecting on:"); + for (AsyncEvent e : debugList) { + System.err.println(opvals(e.interestOps())); + } + } + + String opvals(int i) { + StringBuilder sb = new StringBuilder(); + if ((i & OP_READ) != 0) + sb.append("OP_READ "); + if ((i & OP_CONNECT) != 0) + sb.append("OP_CONNECT "); + if ((i & OP_WRITE) != 0) + sb.append("OP_WRITE "); + return sb.toString(); + } + + @Override + public void run() { + try { + while (true) { + synchronized (this) { + debugList = copy(registrations); + for (AsyncEvent exchange : registrations) { + SelectableChannel c = exchange.channel(); + try { + c.configureBlocking(false); + c.register(selector, + exchange.interestOps(), + exchange); + } catch (IOException e) { + Log.logError("HttpClientImpl: " + e); + c.close(); + // let the exchange deal with it + handleEvent(exchange); + } + } + registrations.clear(); + } + long timeval = getTimeoutValue(); + long now = System.currentTimeMillis(); + int n = selector.select(timeval); + if (n == 0) { + signalTimeouts(now); + continue; + } + Set keys = selector.selectedKeys(); + + for (SelectionKey key : keys) { + if (key.isReadable() || key.isConnectable() || key.isWritable()) { + key.cancel(); + AsyncEvent exchange = (AsyncEvent) key.attachment(); + readyList.add(exchange); + } + } + selector.selectNow(); // complete cancellation + selector.selectedKeys().clear(); + + for (AsyncEvent exchange : readyList) { + if (exchange instanceof AsyncEvent.Blocking) { + exchange.channel().configureBlocking(true); + } else { + assert exchange instanceof AsyncEvent.NonBlocking; + } + executor.synchronize(); + handleEvent(exchange); // will be delegated to executor + } + readyList.clear(); + } + } catch (Throwable e) { + if (!closed) { + System.err.println("HttpClientImpl terminating on error"); + // This terminates thread. So, better just print stack trace + String err = Utils.stackTrace(e); + Log.logError("HttpClientImpl: fatal error: " + err); + } + } + } + + void handleEvent(AsyncEvent e) { + if (closed) { + e.abort(); + } else { + e.handle(); + } + } + } + + /** + * Creates a HttpRequest associated with this group. + * + * @throws IllegalStateException if the group has been stopped + */ + @Override + public HttpRequestBuilderImpl request() { + return new HttpRequestBuilderImpl(this, null); + } + + /** + * Creates a HttpRequest associated with this group. + * + * @throws IllegalStateException if the group has been stopped + */ + @Override + public HttpRequestBuilderImpl request(URI uri) { + return new HttpRequestBuilderImpl(this, uri); + } + + @Override + public SSLContext sslContext() { + Utils.checkNetPermission("getSSLContext"); + return sslContext; + } + + @Override + public Optional sslParameters() { + return Optional.ofNullable(sslParams); + } + + @Override + public Optional authenticator() { + return Optional.ofNullable(authenticator); + } + + @Override + public ExecutorService executorService() { + return executor.userExecutor(); + } + + ExecutorWrapper executorWrapper() { + return executor; + } + + @Override + public boolean pipelining() { + return this.pipelining; + } + + ConnectionPool connectionPool() { + return connections; + } + + @Override + public Redirect followRedirects() { + return followRedirects; + } + + + @Override + public Optional cookieManager() { + return Optional.ofNullable(cookieManager); + } + + @Override + public Optional proxy() { + return Optional.ofNullable(this.proxySelector); + } + + @Override + public Version version() { + return version; + } + + //private final HashMap http2NotSupported = new HashMap<>(); + + boolean getHttp2Allowed() { + return version.equals(Version.HTTP_2); + } + + //void setHttp2NotSupported(String host) { + //http2NotSupported.put(host, false); + //} + + final void initFilters() { + addFilter(AuthenticationFilter.class); + addFilter(RedirectFilter.class); + } + + final void addFilter(Class f) { + filters.addFilter(f); + } + + final List filterChain() { + return filters.getFilterChain(); + } + + // Timer controls. Timers are implemented through timed Selector.select() + // calls. + synchronized void registerTimer(TimeoutEvent event) { + long elapse = event.timevalMillis(); + ListIterator iter = timeouts.listIterator(); + long listval = 0; + event.delta = event.timeval; // in case list empty + TimeoutEvent next; + while (iter.hasNext()) { + next = iter.next(); + listval += next.delta; + if (elapse < listval) { + listval -= next.delta; + event.delta = elapse - listval; + next.delta -= event.delta; + iter.previous(); + break; + } else if (!iter.hasNext()) { + event.delta = event.timeval - listval ; + } + } + iter.add(event); + //debugPrintList("register"); + selmgr.wakeupSelector(); + } + + void debugPrintList(String s) { + System.err.printf("%s: {", s); + for (TimeoutEvent e : timeouts) { + System.err.printf("(%d,%d) ", e.delta, e.timeval); + } + System.err.println("}"); + } + + synchronized void signalTimeouts(long then) { + if (timeouts.isEmpty()) { + return; + } + long now = System.currentTimeMillis(); + long duration = now - then; + ListIterator iter = timeouts.listIterator(); + TimeoutEvent event = iter.next(); + long delta = event.delta; + if (duration < delta) { + event.delta -= duration; + return; + } + event.handle(); + iter.remove(); + while (iter.hasNext()) { + event = iter.next(); + if (event.delta == 0) { + event.handle(); + iter.remove(); + } else { + event.delta += delta; + break; + } + } + //debugPrintList("signalTimeouts"); + } + + synchronized void cancelTimer(TimeoutEvent event) { + ListIterator iter = timeouts.listIterator(); + while (iter.hasNext()) { + TimeoutEvent ev = iter.next(); + if (event == ev) { + if (iter.hasNext()) { + // adjust + TimeoutEvent next = iter.next(); + next.delta += ev.delta; + iter.previous(); + } + iter.remove(); + } + } + } + + // used for the connection window + int getReceiveBufferSize() { + return Utils.getIntegerNetProperty( + "sun.net.httpclient.connectionWindowSize", 256 * 1024 + ); + } + + // returns 0 meaning block forever, or a number of millis to block for + synchronized long getTimeoutValue() { + if (timeouts.isEmpty()) { + return 0; + } else { + return timeouts.get(0).delta; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java new file mode 100644 index 00000000000..ea82531b469 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLParameters; + +/** + * Wraps socket channel layer and takes care of SSL also. + * + * Subtypes are: + * PlainHttpConnection: regular direct TCP connection to server + * PlainProxyConnection: plain text proxy connection + * PlainTunnelingConnection: opens plain text (CONNECT) tunnel to server + * SSLConnection: TLS channel direct to server + * SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel + */ +abstract class HttpConnection implements BufferHandler { + + // address we are connected to. Could be a server or a proxy + final InetSocketAddress address; + final HttpClientImpl client; + protected volatile ByteBuffer buffer; + + HttpConnection(InetSocketAddress address, HttpClientImpl client) { + this.address = address; + this.client = client; + } + + /** + * Public API to this class. addr is the ultimate destination. Any proxies + * etc are figured out from the request. Returns an instance of one of the + * following + * PlainHttpConnection + * PlainTunnelingConnection + * SSLConnection + * SSLTunnelConnection + * + * When object returned, connect() or connectAsync() must be called, which + * when it returns/completes, the connection is usable for requests. + */ + public static HttpConnection getConnection(InetSocketAddress addr, + HttpRequestImpl request) { + return getConnectionImpl(addr, request); + } + + public abstract void connect() throws IOException, InterruptedException; + + public abstract CompletableFuture connectAsync(); + + /** + * Returns whether this connection is connected to its destination + */ + abstract boolean connected(); + + abstract boolean isSecure(); + + abstract boolean isProxied(); + + /** + * Completes when the first byte of the response is available to be read. + */ + abstract CompletableFuture whenReceivingResponse(); + + // must be called before reading any data off connection + // at beginning of response. + ByteBuffer getRemaining() { + ByteBuffer b = buffer; + buffer = null; + return b; + } + + final boolean isOpen() { + return channel().isOpen(); + } + + /* Returns either a plain HTTP connection or a plain tunnelling connection + * for proxied websockets */ + private static HttpConnection getPlainConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpRequestImpl request) { + HttpClientImpl client = request.client(); + + if (request.isWebSocket() && proxy != null) { + return new PlainTunnelingConnection(addr, + proxy, + client, + request.getAccessControlContext()); + } else { + if (proxy == null) { + return new PlainHttpConnection(addr, client); + } else { + return new PlainProxyConnection(proxy, client); + } + } + } + + private static HttpConnection getSSLConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpRequestImpl request, + String[] alpn) { + HttpClientImpl client = request.client(); + if (proxy != null) { + return new SSLTunnelConnection(addr, + client, + proxy, + request.getAccessControlContext()); + } else { + return new SSLConnection(addr, client, alpn); + } + } + + /** + * Main factory method. Gets a HttpConnection, either cached or new if + * none available. + */ + private static HttpConnection getConnectionImpl(InetSocketAddress addr, + HttpRequestImpl request) { + HttpConnection c; + HttpClientImpl client = request.client(); + InetSocketAddress proxy = request.proxy(); + boolean secure = request.secure(); + ConnectionPool pool = client.connectionPool(); + String[] alpn = null; + + if (secure && request.requestHttp2()) { + alpn = new String[1]; + alpn[0] = "h2"; + } + + if (!secure) { + c = pool.getConnection(false, addr, proxy); + if (c != null) { + return c; + } else { + return getPlainConnection(addr, proxy, request); + } + } else { + c = pool.getConnection(true, addr, proxy); + if (c != null) { + return c; + } else { + return getSSLConnection(addr, proxy, request, alpn); + } + } + } + + void returnToCache(HttpHeaders hdrs) { + if (hdrs == null) { + // the connection was closed by server + close(); + return; + } + if (!isOpen()) { + return; + } + ConnectionPool pool = client.connectionPool(); + boolean keepAlive = hdrs.firstValue("Connection") + .map((s) -> !s.equalsIgnoreCase("close")) + .orElse(true); + + if (keepAlive) { + pool.returnToPool(this); + } else { + close(); + } + } + + /** + * Also check that the number of bytes written is what was expected. This + * could be different if the buffer is user-supplied and its internal + * pointers were manipulated in a race condition. + */ + final void checkWrite(long expected, ByteBuffer buffer) throws IOException { + long written = write(buffer); + if (written != expected) { + throw new IOException("incorrect number of bytes written"); + } + } + + final void checkWrite(long expected, + ByteBuffer[] buffers, + int start, + int length) + throws IOException + { + long written = write(buffers, start, length); + if (written != expected) { + throw new IOException("incorrect number of bytes written"); + } + } + + abstract SocketChannel channel(); + + final InetSocketAddress address() { + return address; + } + + void configureBlocking(boolean mode) throws IOException { + channel().configureBlocking(mode); + } + + abstract ConnectionPool.CacheKey cacheKey(); + + /* + static PrintStream ps; + + static { + try { + String propval = Utils.getNetProperty("java.net.httpclient.showData"); + if (propval != null && propval.equalsIgnoreCase("true")) { + ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + synchronized final void debugPrint(String s, ByteBuffer b) { + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = b; + debugPrint(s, bufs, 0, 1); + } + + synchronized final void debugPrint(String s, + ByteBuffer[] bufs, + int start, + int number) { + if (ps == null) { + return; + } + + ps.printf("\n%s:\n", s); + + for (int i=start; i 0x20 && c <= 0x7F) { + ps.printf("%c", (char)c); + } else { + ps.printf("0x%02x ", c); + } + } + } + ps.printf("\n---------------------\n"); + } + + */ + + // overridden in SSL only + SSLParameters sslParameters() { + return null; + } + + // Methods to be implemented for Plain TCP and SSL + + abstract long write(ByteBuffer[] buffers, int start, int number) + throws IOException; + + abstract long write(ByteBuffer buffer) throws IOException; + + /** + * Closes this connection, by returning the socket to its connection pool. + */ + abstract void close(); + + /** + * Returns a ByteBuffer with data, or null if EOF. + */ + final ByteBuffer read() throws IOException { + return read(-1); + } + + /** + * Puts position to limit and limit to capacity so we can resume reading + * into this buffer, but if required > 0 then limit may be reduced so that + * no more than required bytes are read next time. + */ + static void resumeChannelRead(ByteBuffer buf, int required) { + int limit = buf.limit(); + buf.position(limit); + int capacity = buf.capacity() - limit; + if (required > 0 && required < capacity) { + buf.limit(limit + required); + } else { + buf.limit(buf.capacity()); + } + } + + /** + * Blocks ands return requested amount. + */ + final ByteBuffer read(int length) throws IOException { + if (length <= 0) { + buffer = readImpl(length); + return buffer; + } + buffer = readImpl(length); + int required = length - buffer.remaining(); + while (buffer.remaining() < length) { + resumeChannelRead(buffer, required); + int n = readImpl(buffer); + required -= n; + } + return buffer; + } + + final int read(ByteBuffer buffer) throws IOException { + int n = readImpl(buffer); + return n; + } + + /** Reads up to length bytes. */ + protected abstract ByteBuffer readImpl(int length) throws IOException; + + /** Reads as much as possible into given buffer and returns amount read. */ + protected abstract int readImpl(ByteBuffer buffer) throws IOException; + + @Override + public String toString() { + return "HttpConnection: " + channel().toString(); + } + + @Override + public final ByteBuffer getBuffer() { + return client.getBuffer(); + } + + @Override + public final void returnBuffer(ByteBuffer buffer) { + client.returnBuffer(buffer); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java new file mode 100644 index 00000000000..587e0af14bf --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * A read-only view of a set of received HTTP headers. + * + * @since 9 + */ +public interface HttpHeaders { + + /** + * Returns an {@link java.util.Optional} containing the first value of the + * given named (and possibly multi-valued) header. If the header is not + * present, then the returned {@code Optional} is empty. + * + * @param name the header name + * @return an {@code Optional} for the first named value + */ + public Optional firstValue(String name); + + /** + * Returns an {@link java.util.Optional} containing the first value of the + * named header field as an {@literal Optional}. If the header is not + * present, then the Optional is empty. If the header is present but + * contains a value that does not parse as a {@code Long} value, then an + * exception is thrown. + * + * @param name the header name + * @return an {@code Optional} + * @throws NumberFormatException if a value is found, but does not parse as + * a Long + */ + public Optional firstValueAsLong(String name); + + /** + * Returns an unmodifiable List of all of the values of the given named + * header. Always returns a List, which may be empty if the header is not + * present. + * + * @param name the header name + * @return a List of String values + */ + public List allValues(String name); + + /** + * Returns an unmodifiable multi Map view of this HttpHeaders. This + * interface should only be used when it is required to iterate over the + * entire set of headers. + * + * @return the Map + */ + public Map> map(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java new file mode 100644 index 00000000000..c9ff689a931 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +public interface HttpHeaders1 extends HttpHeaders { + public void makeUnmodifiable(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java new file mode 100644 index 00000000000..532625e65da --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Implementation of HttpHeaders. + */ +class HttpHeadersImpl implements HttpHeaders1 { + + private final HashMap> headers; + private boolean isUnmodifiable = false; + + public HttpHeadersImpl() { + headers = new HashMap<>(); + } + + /** + * Replace all List in headers with unmodifiable Lists. Call + * this only after all headers are added. The headers HashMap + * is wrapped with an unmodifiable HashMap in map() + */ + @Override + public void makeUnmodifiable() { + if (isUnmodifiable) + return; + + Set keys = new HashSet<>(headers.keySet()); + for (String key : keys) { + List values = headers.remove(key); + if (values != null) { + headers.put(key, Collections.unmodifiableList(values)); + } + } + isUnmodifiable = true; + } + + @Override + public Optional firstValue(String name) { + List l = headers.get(name); + return Optional.ofNullable(l == null ? null : l.get(0)); + } + + @Override + public List allValues(String name) { + return headers.get(name); + } + + @Override + public Map> map() { + return Collections.unmodifiableMap(headers); + } + + Map> directMap() { + return headers; + } + + // package private mutators + + public HttpHeadersImpl deepCopy() { + HttpHeadersImpl h1 = new HttpHeadersImpl(); + HashMap> headers1 = h1.headers; + Set keys = headers.keySet(); + for (String key : keys) { + List vals = headers.get(key); + LinkedList vals1 = new LinkedList<>(vals); + headers1.put(key, vals1); + } + return h1; + } + + private List getOrCreate(String name) { + List l = headers.get(name); + if (l == null) { + l = new LinkedList<>(); + headers.put(name, l); + } + return l; + } + + void addHeader(String name, String value) { + List l = getOrCreate(name); + l.add(value); + } + + void setHeader(String name, String value) { + List l = getOrCreate(name); + l.clear(); + l.add(value); + } + + @Override + public Optional firstValueAsLong(String name) { + List l = headers.get(name); + if (l == null) { + return Optional.ofNullable(null); + } else { + String v = l.get(0); + Long lv = Long.parseLong(v); + return Optional.of(lv); + } + } + + void clear() { + headers.clear(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java new file mode 100644 index 00000000000..fd177827fe3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.net.*; + +interface HttpRedirectImpl { + + static HttpRedirectImpl getRedirects(java.net.http.HttpClient.Redirect redir) { + switch (redir) { + case NEVER: + return HttpRedirectImpl.NEVER; + case ALWAYS: + return HttpRedirectImpl.ALWAYS; + case SECURE: + return HttpRedirectImpl.SECURE; + case SAME_PROTOCOL: + return HttpRedirectImpl.SAME_PROTOCOL; + } + return HttpRedirectImpl.NEVER; + } + + static HttpClient.Redirect getRedirects(HttpRedirectImpl redir) { + if (redir == HttpRedirectImpl.NEVER) { + return HttpClient.Redirect.NEVER; + } else if (redir == HttpRedirectImpl.ALWAYS) { + return HttpClient.Redirect.ALWAYS; + } else if (redir == HttpRedirectImpl.SECURE) { + return HttpClient.Redirect.SECURE; + } else { + return HttpClient.Redirect.SAME_PROTOCOL; + } + } + + /** + * Called to determine whether the given intermediate response + * with a redirection response code should be redirected. The target URI + * can be obtained from the "Location" header in the given response object. + * + * @param rsp the response from the redirected resource + * @return {@code true} if the redirect should be attempted automatically + * or {@code false} if not. + */ + boolean redirect(HttpResponse rsp); + + /** + * Never redirect. + */ + static HttpRedirectImpl NEVER = (HttpResponse rsp) -> false; + + /** + * Always redirect. + */ + static HttpRedirectImpl ALWAYS = (HttpResponse rsp) -> true; + + /** + * Redirect to same protocol only. Redirection may occur from HTTP URLs to + * other THHP URLs and from HTTPS URLs to other HTTPS URLs. + */ + static HttpRedirectImpl SAME_PROTOCOL = (HttpResponse rsp) -> { + String orig = rsp.request().uri().getScheme().toLowerCase(); + String redirect = URI.create( + rsp.headers().firstValue("Location").orElse("")) + .getScheme().toLowerCase(); + return orig.equals(redirect); + }; + + /** + * Redirect always except from HTTPS URLs to HTTP URLs. + */ + static HttpRedirectImpl SECURE = (HttpResponse rsp) -> { + String orig = rsp.request().uri().getScheme().toLowerCase(); + String redirect = URI.create( + rsp.headers().firstValue("Location").orElse("")) + .getScheme().toLowerCase(); + if (orig.equals("https")) { + return redirect.equals("https"); + } + return true; + }; +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java new file mode 100644 index 00000000000..66f84e360ce --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.URI; +import java.net.ProxySelector; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.*; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.LongConsumer; + +/** + * Represents one HTTP request which can be sent to a server. {@code + * HttpRequest}s are built from {@code HttpRequest} {@link HttpRequest.Builder + * builder}s. {@code HttpRequest} builders are obtained from a {@link HttpClient} + * by calling {@link HttpClient#request(java.net.URI) HttpClient.request}, or + * by calling {@link #create(java.net.URI) HttpRequest.create} which returns a + * builder on the default client. + * A request's {@link java.net.URI}, headers and body can be set. Request bodies + * are provided through a {@link BodyProcessor} object. Once all required + * parameters have been set in the builder, one of the builder methods should be + * called, which sets the request method and returns a {@code HttpRequest}. + * These methods are {@link Builder#GET() GET}, {@link HttpRequest.Builder#POST() + * POST} and {@link HttpRequest.Builder#PUT() PUT} which return a GET, POST or + * PUT request respectively. Alternatively, {@link + * HttpRequest.Builder#method(String) method} can be called to set an arbitrary + * method type (and return a {@code HttpRequest}). Builders can also be copied + * and modified multiple times in order to build multiple related requests that + * differ in some parameters. + * + *

    Two simple, example HTTP interactions are shown below: + *

    + * {@code
    + *      // GET
    + *      HttpResponse response = HttpRequest
    + *          .create(new URI("http://www.foo.com"))
    + *          .headers("Foo", "foovalue", "Bar", "barvalue")
    + *          .GET()
    + *          .response();
    + *
    + *      int statusCode = response.statusCode();
    + *      String responseBody = response.body(asString());
    + *
    + *      // POST
    + *      response = HttpRequest
    + *          .create(new URI("http://www.foo.com"))
    + *          .body(fromString("param1=foo,param2=bar"))
    + *          .POST()
    + *          .response();}
    + * 
    + * + *

    The request is sent and the response obtained by calling one of the + * following methods. + *

    • {@link #response() response} blocks until the entire request has been + * sent and the response status code and headers have been received.
    • + *
    • {@link #responseAsync() responseAsync} sends the request and receives the + * response asynchronously. Returns immediately with a + * {@link java.util.concurrent.CompletableFuture CompletableFuture}<{@link + * HttpResponse}>.
    • + *
    • {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync} + * sends the request asynchronously, expecting multiple responses. This + * capability is of most relevance to HTTP/2 server push, but can be used for + * single responses (HTTP/1.1 or HTTP/2) also.
    • + *
    + * + *

    Once a request has been sent, it is an error to try and send it again. + * + *

    Once a {@code HttpResponse} is received, the headers and response code are + * available. The body can then be received by calling one of the body methods + * on {@code HttpResponse}. + * + *

    See below for discussion of synchronous versus asynchronous usage. + * + *

    Request bodies + * + *

    Request bodies are sent using one of the request processor implementations + * below provided in {@code HttpRequest}, or else a custom implementation can be + * used. + *

      + *
    • {@link #fromByteArray(byte[]) } from byte array
    • + *
    • {@link #fromByteArrays(java.util.Iterator) fromByteArrays(Iterator)} + * from an iterator of byte arrays
    • + *
    • {@link #fromFile(java.nio.file.Path) fromFile(Path)} from the file located + * at the given Path
    • + *
    • {@link #fromString(java.lang.String) fromString(String)} from a String
    • + *
    • {@link #fromInputStream(java.io.InputStream) fromInputStream(InputStream)} + * request body from InputStream
    • + *
    • {@link #noBody() } no request body is sent
    • + *
    + * + *

    Response bodies + * + *

    Responses bodies are handled by the {@link HttpResponse.BodyProcessor} + * {@code } supplied to the {@link HttpResponse#body(HttpResponse.BodyProcessor) + * HttpResponse.body} and {@link HttpResponse#bodyAsync(HttpResponse.BodyProcessor) + * HttpResponse.bodyAsync} methods. Some implementations of {@code + * HttpResponse.BodyProcessor} are provided in {@link HttpResponse}: + *

      + *
    • {@link HttpResponse#asByteArray() } stores the body in a byte array
    • + *
    • {@link HttpResponse#asString()} stores the body as a String
    • + *
    • {@link HttpResponse#asFile(java.nio.file.Path) } stores the body in a + * named file
    • + *
    • {@link HttpResponse#ignoreBody() } ignores any received response body
    • + *
    + * + *

    The output of a response processor is the response body, and its + * parameterized type {@code T} determines the type of the body object returned + * from {@code HttpResponse.body} and {@code HttpResponse.bodyAsync}. Therefore, + * as an example, the second response processor in the list above has the type + * {@code HttpResponse.BodyProcessor} which means the type returned by + * {@code HttpResponse.body()} is a String. Response processors can be defined + * to return potentially any type as body. + * + *

    Multi responses + * + *

    With HTTP/2 it is possible for a server to return a main response and zero + * or more additional responses (known as server pushes) to a client-initiated + * request. These are handled using a special response processor called {@link + * HttpResponse.MultiProcessor}. + * + *

    Blocking/asynchronous behavior and thread usage + * + *

    There are two styles of request sending: synchronous and + * asynchronous. {@link #response() response} blocks the calling thread + * until the request has been sent and the response received. + * + *

    {@link #responseAsync() responseAsync} is asynchronous and returns + * immediately with a {@link java.util.concurrent.CompletableFuture}<{@link + * HttpResponse}> and when this object completes (in a background thread) the + * response has been received. + * + *

    {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync} + * is the variant for multi responses and is also asynchronous. + * + *

    CompletableFutures can be combined in different ways to declare the + * dependencies among several asynchronous tasks, while allowing for the maximum + * level of parallelism to be utilized. + * + *

    Security checks + * + *

    If a security manager is present then security checks are performed by + * the {@link #response() } and {@link #responseAsync() } methods. A {@link + * java.net.URLPermission} or {@link java.net.SocketPermission} is required to + * access any destination origin server and proxy server utilised. URLPermissions + * should be preferred in policy files over SocketPermissions given the more + * limited scope of URLPermission. Permission is always implicitly granted to a + * system's default proxies. The URLPermission form used to access proxies uses + * a method parameter of "CONNECT" (for all kinds of proxying) and a url string + * of the form "socket://host:port" where host and port specify the proxy's + * address. + * + *

    Examples + *

    + *     import static java.net.http.HttpRequest.*;
    + *     import static java.net.http.HttpResponse.*;
    + *
    + *     //Simple blocking
    + *
    + *     HttpResponse r1 = HttpRequest.create(new URI("http://www.foo.com/"))
    + *                                  .GET()
    + *                                 .response();
    + *     int responseCode = r1.statusCode());
    + *     String body = r1.body(asString());
    + *
    + *     HttpResponse r2 = HttpRequest.create(new URI("http://www.foo.com/"))
    + *                                  .GET()
    + *                                  .response();
    + *
    + *     System.out.println("Response was " + r1.statusCode());
    + *     Path body1 = r2.body(asFile(Paths.get("/tmp/response.txt")));
    + *     // Content stored in /tmp/response.txt
    + *
    + *     HttpResponse r3 = HttpRequest.create(new URI("http://www.foo.com/"))
    + *                                  .body(fromString("param1=1, param2=2"))
    + *                                  .POST()
    + *                                  .response();
    + *
    + *     Void body2 = r3.body(ignoreBody()); // body is Void in this case
    + * 
    + * + *

    Asynchronous Example + * + *

    All of the above examples will work asynchronously, if {@link + * #responseAsync()} is used instead of {@link #response()} in which case the + * returned object is a {@code CompletableFuture} instead of + * {@code HttpResponse}. The following example shows how multiple requests can + * be sent asynchronously. It also shows how dependent asynchronous operations + * (receiving response, and receiving response body) can be chained easily using + * one of the many methods in {@code CompletableFuture}. + *

    + * {@code
    + *      // fetch a list of target URIs asynchronously and store them in Files.
    + *
    + *      List targets = ...
    + *
    + *      List> futures = targets
    + *          .stream()
    + *          .map(target -> {
    + *              return HttpRequest
    + *                  .create(target)
    + *                  .GET()
    + *                  .responseAsync()
    + *                  .thenCompose(response -> {
    + *                      Path dest = Paths.get("base", target.getPath());
    + *                      if (response.statusCode() == 200) {
    + *                          return response.bodyAsync(asFile(dest));
    + *                      } else {
    + *                          return CompletableFuture.completedFuture(dest);
    + *                      }
    + *                  })
    + *                  // convert Path -> File
    + *                  .thenApply((Path dest) -> {
    + *                      return dest.toFile();
    + *                  });
    + *              })
    + *          .collect(Collectors.toList());
    + *
    + *      // all async operations waited for here
    + *
    + *      CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    + *          .join();
    + *
    + *      // all elements of futures have completed and can be examined.
    + *      // Use File.exists() to check whether file was successfully downloaded
    + * }
    + * 
    + * + * @since 9 + */ +public abstract class HttpRequest { + + HttpRequest() {} + + /** + * A builder of {@link HttpRequest}s. {@code HttpRequest.Builder}s are + * created by calling {@link HttpRequest#create(URI)} or {@link + * HttpClient#request(URI)}. + * + *

    Each of the setter methods in this class modifies the state of the + * builder and returns this (ie. the same instance). The methods are + * not synchronized and should not be called from multiple threads without + * external synchronization. + * + *

    The build methods return a new {@code HttpRequest} each time they are + * called. + * + * @since 9 + */ + public abstract static class Builder { + + Builder() {} + + /** + * Sets this HttpRequest's request URI. + * + * @param uri the request URI + * @return this request builder + */ + public abstract Builder uri(URI uri); + + /** + * Specifies whether this request will automatically follow redirects + * issued by the server. The default value for this setting is the value + * of {@link HttpClient#followRedirects() } + * + * @param policy the redirection policy + * @return this request builder + */ + public abstract Builder followRedirects(HttpClient.Redirect policy); + + /** + * Request server to acknowledge request before sending request + * body. This is disabled by default. If enabled, the server is requested + * to send an error response or a 100-Continue response before the client + * sends the request body. This means the request processor for the + * request will not be invoked until this interim response is received. + * + * @param enable {@code true} if Expect continue to be sent + * @return this request builder + */ + public abstract Builder expectContinue(boolean enable); + + /** + * Overrides the {@link HttpClient#version() } setting for this + * request. + * + * @param version the HTTP protocol version requested + * @return this request builder + */ + public abstract Builder version(HttpClient.Version version); + + /** + * Adds the given name value pair to the set of headers for this request. + * + * @param name the header name + * @param value the header value + * @return this request builder + */ + public abstract Builder header(String name, String value); + + /** + * Overrides the ProxySelector set on the request's client for this + * request. + * + * @param proxy the ProxySelector to use + * @return this request builder + */ + public abstract Builder proxy(ProxySelector proxy); + + /** + * Adds the given name value pairs to the set of headers for this + * request. The supplied Strings must alternate as names and values. + * + * @param headers the list of String name value pairs + * @return this request builder + * @throws IllegalArgumentException if there is an odd number of + * parameters + */ + public abstract Builder headers(String... headers); + + /** + * Sets a timeout for this request. If the response is not received + * within the specified timeout then a {@link HttpTimeoutException} is + * thrown from {@link #response() } or {@link #responseAsync() } + * completes exceptionally with a {@code HttpTimeoutException}. + * + * @param unit the timeout units + * @param timeval the number of units to wait for + * @return this request builder + */ + public abstract Builder timeout(TimeUnit unit, long timeval); + + /** + * Sets the given name value pair to the set of headers for this + * request. This overwrites any previously set values for name. + * + * @param name the header name + * @param value the header value + * @return this request builder + */ + public abstract Builder setHeader(String name, String value); + + /** + * Sets a request body for this builder. See {@link HttpRequest} + * for example {@code BodyProcessor} implementations. + * If no body is specified, then no body is sent with the request. + * + * @param reqproc the request body processor + * @return this request builder + */ + public abstract Builder body(BodyProcessor reqproc); + + /** + * Builds and returns a GET {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest GET(); + + /** + * Builds and returns a POST {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest POST(); + + /** + * Builds and returns a PUT {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest PUT(); + + /** + * Builds and returns a {@link HttpRequest} from this builder using + * the given method String. The method string is case-sensitive, and + * may be rejected if an upper-case string is not used. + * + * @param method the method to use + * @return a {@code HttpRequest} + * @throws IllegalArgumentException if an unrecognised method is used + */ + public abstract HttpRequest method(String method); + + /** + * Returns an exact duplicate copy of this Builder based on current + * state. The new builder can then be modified independently of this + * builder. + * + * @return an exact copy of this Builder + */ + public abstract Builder copy(); + } + + /** + * Creates a HttpRequest builder from the default HttpClient. + * + * @param uri the request URI + * @return a new request builder + */ + public static HttpRequest.Builder create(URI uri) { + return HttpClient.getDefault().request(uri); + } + + /** + * Returns the follow-redirects setting for this request. + * + * @return follow redirects setting + */ + public abstract HttpClient.Redirect followRedirects(); + + /** + * Returns the response to this request, by sending it and blocking if + * necessary to get the response. The {@link HttpResponse} contains the + * response status and headers. + * + * @return a HttpResponse for this request + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation was interrupted + * @throws SecurityException if the caller does not have the required + * permission + * @throws IllegalStateException if called more than once or if + * responseAsync() called previously + */ + public abstract HttpResponse response() + throws IOException, InterruptedException; + + /** + * Sends the request and returns the response asynchronously. This method + * returns immediately with a {@link CompletableFuture}<{@link + * HttpResponse}> + * + * @return a {@code CompletableFuture} + * @throws IllegalStateException if called more than once or if response() + * called previously. + */ + public abstract CompletableFuture responseAsync(); + + /** + * Sends the request asynchronously expecting multiple responses. + * + *

    This method must be given a {@link HttpResponse.MultiProcessor} to + * handle the multiple responses. + * + *

    If a security manager is set, the caller must possess a {@link + * java.net.URLPermission} for the request's URI, method and any user set + * headers. The security manager is also checked for each incoming + * additional server generated request/response. Any request that fails the + * security check, is canceled and ignored. + * + *

    This method can be used for both HTTP/1.1 and HTTP/2, but in cases + * where multiple responses are not supported, the MultiProcessor + * only receives the main response. + * + *

    The aggregate {@code CompletableFuture} returned from this method + * returns a {@code } defined by the {@link HttpResponse.MultiProcessor} + * implementation supplied. This will typically be a Collection of + * HttpResponses or of some response body type. + * + * @param the aggregate response type + * @param rspproc the MultiProcessor for the request + * @return a {@code CompletableFuture} + * @throws IllegalStateException if the request has already been sent. + */ + public abstract CompletableFuture + multiResponseAsync(HttpResponse.MultiProcessor rspproc); + + /** + * Returns the request method for this request. If not set explicitly, + * the default method for any request is "GET". + * + * @return this request's method + */ + public abstract String method(); + + /** + * Returns this request's {@link HttpRequest.Builder#expectContinue(boolean) + * expect continue } setting. + * + * @return this request's expect continue setting + */ + public abstract boolean expectContinue(); + + /** + * Returns this request's request URI. + * + * @return this request's URI + */ + public abstract URI uri(); + + /** + * Returns this request's {@link HttpClient}. + * + * @return this request's HttpClient + */ + public abstract HttpClient client(); + + /** + * Returns the HTTP protocol version that this request will use or used. + * + * @return HTTP protocol version + */ + public abstract HttpClient.Version version(); + + /** + * The (user-accessible) request headers that this request was (or will be) + * sent with. + * + * @return this request's HttpHeaders + */ + public abstract HttpHeaders headers(); + + /** + * Returns a request processor whose body is the given String, converted + * using the {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} + * character set. + * + * @param body the String containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromString(String body) { + return fromString(body, StandardCharsets.ISO_8859_1); + } + + /** + * A request processor that takes data from the contents of a File. + * + * @param path the path to the file containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromFile(Path path) { + FileChannel fc; + long size; + + try { + fc = FileChannel.open(path); + size = fc.size(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return new BodyProcessor() { + LongConsumer flow; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + // could return exact file length, but for now -1 + this.flow = flow; + flow.accept(1); + if (size != 0) { + return size; + } else { + return -1; + } + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException { + int n = fc.read(buffer); + if (n == -1) { + fc.close(); + return true; + } + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + try { + fc.close(); + } catch (IOException ex) { + Log.logError(ex.toString()); + } + } + }; + } + + /** + * Returns a request processor whose body is the given String, converted + * using the given character set. + * + * @param s the String containing the body + * @param charset the character set to convert the string to bytes + * @return a BodyProcessor + */ + public static BodyProcessor fromString(String s, Charset charset) { + return fromByteArray(s.getBytes(charset)); + } + + /** + * Returns a request processor whose body is the given byte array. + * + * @param buf the byte array containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArray(byte[] buf) { + return fromByteArray(buf, 0, buf.length); + } + + /** + * Returns a request processor whose body is the content of the given byte + * array length bytes starting from the specified offset. + * + * @param buf the byte array containing the body + * @param offset the offset of the first byte + * @param length the number of bytes to use + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArray(byte[] buf, int offset, int length) { + + return new BodyProcessor() { + LongConsumer flow; + byte[] barray; + int index; + int sent; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + barray = buf; + index = offset; + return length; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + if (sent == length) { + return true; + } + + int remaining = buffer.remaining(); + int left = length - sent; + int n = remaining > left ? left : remaining; + buffer.put(barray, index, n); + index += n; + sent += n; + flow.accept(1); + return sent == length; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor that takes data from an Iterator of byte arrays. + * + * @param iter an Iterator of byte arrays + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArrays(Iterator iter) { + + return new BodyProcessor() { + LongConsumer flow; + byte[] current; + int curIndex; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + return -1; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + int remaining; + + while ((remaining = buffer.remaining()) > 0) { + if (current == null) { + if (!iter.hasNext()) { + return true; + } + current = iter.next(); + curIndex = 0; + } + int n = Math.min(remaining, current.length - curIndex); + buffer.put(current, curIndex, n); + curIndex += n; + + if (curIndex == current.length) { + current = null; + flow.accept(1); + return false; + } + } + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor that reads its data from an InputStream. + * + * @param stream an InputStream + * @return a BodyProcessor + */ + public static BodyProcessor fromInputStream(InputStream stream) { + // for now, this blocks. It could be offloaded to a separate thread + // to do reading and guarantee that onRequestBodyChunk() won't block + return new BodyProcessor() { + LongConsumer flow; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + return -1; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + int remaining = buffer.remaining(); + int n = stream.read(buffer.array(), buffer.arrayOffset(), remaining); + if (n == -1) { + stream.close(); + return true; + } + buffer.position(buffer.position() + n); + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor which sends no request body. + * + * @return a BodyProcessor + */ + public static BodyProcessor noBody() { + return new BodyProcessor() { + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + return 0; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + throw new InternalError("should never reach here"); + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor which obtains the request body from some source. + * Implementations of this interface are provided which allow request bodies + * to be supplied from standard types, such as {@code String, byte[], File, + * InputStream}. Other implementations can be provided. + * + *

    The methods of this interface may be called from multiple threads, + * but only one method is invoked at a time, and behaves as if called from + * one thread. + * + *

    See {@link HttpRequest} for implementations that take request bodies + * from {@code byte arrays, Strings, Paths} etc. + * + * @since 9 + */ + public interface BodyProcessor { + + /** + * Called before a request is sent. Is expected to return the content + * length of the request body. Zero means no content. Less than zero + * means an unknown positive content-length, and the body will be + * streamed. + * + *

    The flowController object must be used to manage the flow of + * calls to {@link #onRequestBodyChunk(ByteBuffer)}. The typical usage + * for a non-blocking processor is to call it once inside + * onRequestStart() and once during each call to onRequestBodyChunk(). + * + * @param hr the request + * @param flowController the HttpFlowController + * @return the content length + * @throws IOException if an I/O error occurs + */ + long onRequestStart(HttpRequest hr, LongConsumer flowController) + throws IOException; + + /** + * Called if sending a request body fails. + * + * @implSpec The default implementation does nothing. + * + * @param t the Throwable that caused the failure + */ + default void onRequestError(Throwable t) { } + + /** + * Called to obtain a buffer of data to send. The data must be placed + * in the provided buffer. The implementation should not block. The + * boolean return code notifies the protocol implementation if the + * supplied buffer is the final one (or not). + * + * @param buffer a ByteBuffer to write data into + * @return whether or not this is the last buffer + * @throws IOException if an I/O error occurs + */ + boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException; + + /** + * Called when the request body has been completely sent. + * + * @implSpec The default implementation does nothing + */ + default void onComplete() { + // TODO: need to call this + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java new file mode 100644 index 00000000000..bc04ab3e921 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.net.URI; +import java.net.ProxySelector; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +class HttpRequestBuilderImpl extends HttpRequest.Builder { + + private HttpHeadersImpl userHeaders; + private URI uri; + private String method; + private HttpClient.Redirect followRedirects; + private boolean expectContinue; + private HttpRequest.BodyProcessor body; + private HttpClient.Version version; + private final HttpClientImpl client; + private ProxySelector proxy; + private long timeval = 0; + + public HttpRequestBuilderImpl(HttpClientImpl client, URI uri) { + this.client = client; + this.uri = uri; + this.version = client.version(); + this.userHeaders = new HttpHeadersImpl(); + } + + @Override + public HttpRequestBuilderImpl body(HttpRequest.BodyProcessor reqproc) { + Objects.requireNonNull(reqproc); + this.body = reqproc; + return this; + } + + @Override + public HttpRequestBuilderImpl uri(URI uri) { + Objects.requireNonNull(uri); + this.uri = uri; + return this; + } + + @Override + public HttpRequestBuilderImpl followRedirects(HttpClient.Redirect follow) { + Objects.requireNonNull(follow); + this.followRedirects = follow; + return this; + } + + @Override + public HttpRequestBuilderImpl header(String name, String value) { + Objects.requireNonNull(name); + Objects.requireNonNull(value); + Utils.validateToken(name, "invalid header name"); + userHeaders.addHeader(name, value); + return this; + } + + @Override + public HttpRequestBuilderImpl headers(String... params) { + Objects.requireNonNull(params); + if (params.length % 2 != 0) { + throw new IllegalArgumentException("wrong number of parameters"); + } + for (int i=0; i DISALLOWED_HEADERS_SET = Set.of( + "authorization", "connection", "cookie", "content-length", + "date", "expect", "from", "host", "origin", "proxy-authorization", + "referer", "user-agent", "upgrade", "via", "warning"); + + + // we silently drop headers that are disallowed + private void dropDisallowedHeaders() { + Set hdrnames = userHeaders.directMap().keySet(); + + hdrnames.removeIf((s) -> + DISALLOWED_HEADERS_SET.contains(s.toLowerCase()) + ); + } + + private synchronized void receiving() { + if (receiving) { + throw new IllegalStateException("already receiving response"); + } + receiving = true; + } + + /* + * Response filters may result in a new HttpRequestImpl being created + * (but still associated with the same API HttpRequest) and the process + * is repeated. + */ + @Override + public HttpResponse response() throws IOException, InterruptedException { + receiving(); // TODO: update docs + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + return exchange.response(); + } + + @Override + public synchronized CompletableFuture responseAsync() { + receiving(); // TODO: update docs + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + return exchange.responseAsync(null) + .thenApply((r) -> (HttpResponse)r); + } + + public CompletableFuture + sendAsyncMulti(HttpResponse.MultiProcessor rspproc) { + // To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean expectContinue() { return expectContinue; } + + public boolean requestHttp2() { + return version.equals(HttpClient.Version.HTTP_2); + //return client.getHttp2Allowed(); + } + + AccessControlContext getAccessControlContext() { return acc; } + + InetSocketAddress proxy() { + ProxySelector ps = this.proxy; + if (ps == null) { + ps = client.proxy().orElse(null); + } + if (ps == null || method.equalsIgnoreCase("CONNECT")) { + return null; + } + return (InetSocketAddress)ps.select(uri).get(0).address(); + } + + boolean secure() { return secure; } + + void isWebSocket(boolean is) { + isWebSocket = is; + } + + boolean isWebSocket() { + return isWebSocket; + } + + /** Returns the follow-redirects setting for this request. */ + @Override + public java.net.http.HttpClient.Redirect followRedirects() { + return getRedirects(followRedirects); + } + + HttpRedirectImpl followRedirectsImpl() { return followRedirects; } + + /** + * Returns the request method for this request. If not set explicitly, + * the default method for any request is "GET". + */ + @Override + public String method() { return method; } + + @Override + public URI uri() { return uri; } + + HttpHeadersImpl getUserHeaders() { return userHeaders; } + + HttpHeadersImpl getSystemHeaders() { return systemHeaders; } + + HttpClientImpl getClient() { return client; } + + BodyProcessor requestProcessor() { return requestProcessor; } + + @Override + public Version version() { return version; } + + void addSystemHeader(String name, String value) { + systemHeaders.addHeader(name, value); + } + + void setSystemHeader(String name, String value) { + systemHeaders.setHeader(name, value); + } + + long timeval() { return timeval; } + + @Override + public CompletableFuture + multiResponseAsync(MultiProcessor rspproc) { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java new file mode 100644 index 00000000000..c1ff5adb44e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java @@ -0,0 +1,977 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.net.http; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.LongConsumer; +import javax.net.ssl.SSLParameters; + +/** + * Represents a response to a {@link HttpRequest}. A {@code HttpResponse} is + * available when the response status code and headers have been received, but + * before the response body is received. + * + *

    Methods are provided in this class for accessing the response headers, + * and status code immediately and also methods for retrieving the response body. + * Static methods are provided which implement {@link BodyProcessor} for + * standard body types such as {@code String, byte arrays, files}. + * + *

    The {@link #body(BodyProcessor) body} or {@link #bodyAsync(BodyProcessor) + * bodyAsync} which retrieve any response body must be called to ensure that the + * TCP connection can be re-used subsequently, and any response trailers + * accessed, if they exist, unless it is known that no response body was received. + * + * @since 9 + */ +public abstract class HttpResponse { + + HttpResponse() { } + + /** + * Returns the status code for this response. + * + * @return the response code + */ + public abstract int statusCode(); + + /** + * Returns the {@link HttpRequest} for this response. + * + * @return the request + */ + public abstract HttpRequest request(); + + /** + * Returns the received response headers. + * + * @return the response headers + */ + public abstract HttpHeaders headers(); + + /** + * Returns the received response trailers, if there are any. This must only + * be called after the response body has been received. + * + * @return the response trailers (may be empty) + * @throws IllegalStateException if the response body has not been received + * yet + */ + public abstract HttpHeaders trailers(); + + /** + * Returns the body, blocking if necessary. The type T is determined by the + * {@link BodyProcessor} implementation supplied. The body object will be + * returned immediately if it is a type (such as {@link java.io.InputStream} + * which reads the data itself. If the body object represents the fully read + * body then it blocks until it is fully read. + * + * @param the type of the returned body object + * @param processor the processor to handle the response body + * @return the body + * @throws java.io.UncheckedIOException if an I/O error occurs reading the + * response + */ + public abstract T body(BodyProcessor processor); + + /** + * Returns a {@link java.util.concurrent.CompletableFuture} of type T. This + * always returns immediately and the future completes when the body object + * is available. The body will be available immediately if it is a type + * (such as {@link java.io.InputStream} which reads the data itself. If the + * body object represents the fully read body then it will not be available + * until it is fully read. + * + * @param the type of the returned body object + * @param processor the processor to handle the response body + * @return a CompletableFuture + */ + public abstract CompletableFuture bodyAsync(BodyProcessor processor); + + /** + * Returns the {@link javax.net.ssl.SSLParameters} in effect for this + * response. Returns {@code null} if this is not a https response. + * + * @return the SSLParameters associated with the response + */ + public abstract SSLParameters sslParameters(); + + /** + * Returns the URI that the response was received from. This may be + * different from the request URI if redirection occurred. + * + * @return the URI of the response + */ + public abstract URI uri(); + + /** + * Returns the HTTP protocol version that was used for this response. + * + * @return HTTP protocol version + */ + public abstract HttpClient.Version version(); + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}> where + * the file is created if it does not already exist. When the Path object is + * returned, the body has been completely written to the file. + * + * @param file the file to store the body in + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFile(Path file) { + return asFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + } + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}> where + * the download directory is specified, but the filename is obtained from + * the Content-Disposition response header. The Content-Disposition header + * must specify the attachment type and must also contain a + * filename parameter. If the filename specifies multiple path + * components only the final component is used as the filename (with the + * given directory name). When the Path object is returned, the body has + * been completely written to the file. The returned Path is the combination + * of the supplied directory name and the file name supplied by the server. + * If the destination directory does not exist or cannot be written to, then + * the response will fail with an IOException. + * + * @param directory the directory to store the file in + * @param openOptions open options + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFileDownload(Path directory, + OpenOption... openOptions) { + return new AbstractResponseProcessor() { + + FileChannel fc; + Path file; + + @Override + public Path onResponseBodyStartImpl(long contentLength, + HttpHeaders headers) + throws IOException + { + String dispoHeader = headers.firstValue("Content-Disposition") + .orElseThrow(() -> new IOException("No Content-Disposition")); + if (!dispoHeader.startsWith("attachment;")) { + throw new IOException("Unknown Content-Disposition type"); + } + int n = dispoHeader.indexOf("filename="); + if (n == -1) { + throw new IOException("Bad Content-Disposition type"); + } + String disposition = dispoHeader.substring(n + 9, + dispoHeader.lastIndexOf(';')); + file = Paths.get(directory.toString(), disposition); + fc = FileChannel.open(file, openOptions); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + fc.write(b); + } + + @Override + public Path onResponseComplete() throws IOException { + fc.close(); + return file; + } + + @Override + public void onResponseError(Throwable t) { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + } + } + }; + } + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}>. + * + *

    {@link HttpResponse}s returned using this response processor complete + * after the entire response, including body has been read. + * + * @param file the filename to store the body in + * @param openOptions any options to use when opening/creating the file + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFile(Path file, + OpenOption... openOptions) { + return new AbstractResponseProcessor() { + + FileChannel fc; + + @Override + public Path onResponseBodyStartImpl(long contentLength, + HttpHeaders headers) + throws IOException + { + fc = FileChannel.open(file, openOptions); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException + { + fc.write(b); + } + + @Override + public Path onResponseComplete() throws IOException { + fc.close(); + return file; + } + + @Override + public void onResponseError(Throwable t) { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + } + } + }; + } + + static class ByteArrayResponseProcessor { + + static final int INITIAL_BUFLEN = 1024; + + byte[] buffer; + int capacity; + boolean knownLength; + int position; + + ByteArrayResponseProcessor() { } + + public byte[] onStart(long contentLength) throws IOException { + if (contentLength > Integer.MAX_VALUE) { + throw new IllegalArgumentException( + "byte array response limited to MAX_INT size"); + } + capacity = (int) contentLength; + if (capacity != -1) { + buffer = new byte[capacity]; + knownLength = true; + } else { + buffer = new byte[INITIAL_BUFLEN]; + capacity = INITIAL_BUFLEN; + knownLength = false; + } + position = 0; + return null; + } + + public void onBodyContent(ByteBuffer b) throws IOException { + int toCopy = b.remaining(); + int size = capacity; + if (toCopy > capacity - position) { + // resize + size += toCopy * 2; + } + if (size != capacity) { + if (knownLength) { + // capacity should have been right from start + throw new IOException("Inconsistent content length"); + } + byte[] newbuf = new byte[size]; + System.arraycopy(buffer, 0, newbuf, 0, position); + buffer = newbuf; + capacity = size; + } + int srcposition = b.arrayOffset() + b.position(); + System.arraycopy(b.array(), srcposition, buffer, position, toCopy); + b.position(b.limit()); + position += toCopy; + } + + public byte[] onComplete() throws IOException { + if (knownLength) { + if (position != capacity) { + throw new IOException("Wrong number of bytes received"); + } + return buffer; + } + byte[] buf1 = new byte[position]; + System.arraycopy(buffer, 0, buf1, 0, position); + return buf1; + } + + public void onError(Throwable t) { + // TODO: + } + } + + static final byte[] EMPTY = new byte[0]; + + /** + * Returns a response processor which supplies the response body to the + * given Consumer. Each time data is received the consumer is invoked with a + * byte[] containing at least one byte of data. After the final buffer is + * received, the consumer is invoked one last time, with an empty byte + * array. + * + * @param consumer a Consumer to accept the response body + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asByteArrayConsumer(Consumer consumer) { + return new AbstractResponseProcessor() { + @Override + public Void onResponseBodyStartImpl(long clen, + HttpHeaders h) + throws IOException + { + return null; + } + + @Override + public void onResponseError(Throwable t) { + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + if (!b.hasRemaining()) { + return; + } + byte[] buf = new byte[b.remaining()]; + b.get(buf); + consumer.accept(buf); + } + + @Override + public Void onResponseComplete() throws IOException { + consumer.accept(EMPTY); + return null; + } + }; + } + + /** + * Returns a BodyProcessor which delivers the response data to a + * {@link java.util.concurrent.Flow.Subscriber}{@code ByteBuffer}. + *

    + * The given {@code Supplier} is invoked when the Flow is completed in + * order to convert the flow data into the U object that is returned as the + * response body. + * + * @param the response body type + * @param subscriber the Flow.Subscriber + * @param bufferSize the maximum number of bytes of data to be supplied in + * each ByteBuffer + * @param bodySupplier an object that converts the received data to the body + * type U. + * @return a BodyProcessor + * + * public static BodyProcessor> + * asFlowSubscriber() { + * + * return new BodyProcessor() { Flow.Subscriber subscriber; + * LongConsumer flowController; FlowSubscription subscription; Supplier + * bodySupplier; int bufferSize; // down-stream Flow window. long + * buffersWindow; // upstream window long bytesWindow; + * LinkedList buffers = new LinkedList<>(); + * + * class FlowSubscription implements Subscription { int recurseLevel = 0; + * @Override public void request(long n) { boolean goodToGo = recurseLevel++ + * == 0; + * + * while (goodToGo && buffers.size() > 0 && n > 0) { ByteBuffer buf = + * buffers.get(0); subscriber.onNext(buf); n--; } buffersWindow += n; + * flowController.accept(n * bufferSize); recurseLevel--; } + * + * @Override public void cancel() { // ?? set flag and throw exception on + * next receipt of buffer } } + * + * @Override public U onResponseBodyStart(long contentLength, HttpHeaders + * responseHeaders, LongConsumer flowController) throws IOException { + * this.subscriber = subscriber; this.flowController = flowController; + * this.subscription = new FlowSubscription(); this.bufferSize = bufferSize; + * subscriber.onSubscribe(subscription); return null; } + * + * @Override public void onResponseError(Throwable t) { + * subscriber.onError(t); } + * + * @Override public void onResponseBodyChunk(ByteBuffer b) throws + * IOException { if (buffersWindow > 0) { buffersWindow --; + * subscriber.onNext(b); } else { buffers.add(b); // or could combine + * buffers? } } + * + * @Override public U onResponseComplete() throws IOException { + * subscriber.onComplete(); return bodySupplier.get(); } }; } + */ + private static final ByteBuffer EOF = ByteBuffer.allocate(0); + private static final ByteBuffer CLOSED = ByteBuffer.allocate(0); + + // prototype using ByteBuffer based flow control. InputStream feeds off a + // BlockingQueue. Size of Q is determined from the the bufsize (bytes) and + // the default ByteBuffer size. bufsize should be a reasonable multiple of + // ByteBuffer size to prevent underflow/starvation. The InputStream updates + // the flowControl window by one as each ByteBuffer is fully consumed. + // Special sentinels are used to indicate stream closed and EOF. + /** + * Returns a response body processor which provides an InputStream to read + * the body. + * + * @implNote This mechanism is provided primarily for backwards + * compatibility for code that expects InputStream. It is recommended for + * better performance to use one of the other response processor + * implementations. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asInputStream() { + return new BodyProcessor() { + int queueSize = 2; + private volatile Throwable throwable; + + BlockingQueue queue = new LinkedBlockingQueue<>(); + + private void closeImpl() { + try { + queue.put(CLOSED); + } catch (InterruptedException e) { } + } + + @Override + public InputStream onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException + { + flowController.accept(queueSize); + + return new InputStream() { + ByteBuffer buffer; + + @Override + public int read() throws IOException { + byte[] bb = new byte[1]; + int n = read(bb, 0, 1); + if (n == -1) { + return -1; + } else { + return bb[0]; + } + } + + @Override + public int read(byte[] bb) throws IOException { + return read(bb, 0, bb.length); + } + + @Override + public int read(byte[] bb, int offset, int length) + throws IOException + { + int n; + if (getBuffer()) { + return -1; // EOF + } else { + int remaining = buffer.remaining(); + if (length >= remaining) { + buffer.get(bb, offset, remaining); + return remaining; + } else { + buffer.get(bb, offset, length); + return length; + } + } + } + + @Override + public void close() { + closeImpl(); + } + + private boolean getBuffer() throws IOException { + while (buffer == null || (buffer != EOF && + buffer != CLOSED && !buffer.hasRemaining())) { + try { + buffer = queue.take(); + flowController.accept(1); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + if (buffer == CLOSED) { + if (throwable != null) { + if (throwable instanceof IOException) { + throw (IOException) throwable; + } else { + throw new IOException(throwable); + } + } + throw new IOException("Closed"); + } + + if (buffer == EOF) { + return true; // EOF + } + return false; // not EOF + } + + }; + } + + @Override + public void onResponseError(Throwable t) { + throwable = t; + closeImpl(); + } + + @Override + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + try { + queue.put(Utils.copy(b)); + } catch (InterruptedException e) { + // shouldn't happen as queue should never block + throw new IOException(e); + } + } + + @Override + public InputStream onResponseComplete() throws IOException { + try { + queue.put(EOF); + } catch (InterruptedException e) { + throw new IOException(e); // can't happen + } + return null; + } + + }; + } + + /** + * Common super class that takes care of flow control + * + * @param + */ + private static abstract class AbstractResponseProcessor + implements BodyProcessor + { + LongConsumer flowController; + + @Override + public final T onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException + { + this.flowController = flowController; + flowController.accept(1); + return onResponseBodyStartImpl(contentLength, responseHeaders); + } + + public abstract T onResponseBodyStartImpl(long contentLength, + HttpHeaders responseHeaders) + throws IOException; + + public abstract void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException; + + @Override + public final void onResponseBodyChunk(ByteBuffer b) throws IOException { + onResponseBodyChunkImpl(b); + flowController.accept(1); + } + } + + /** + * Returns a {@link BodyProcessor}<byte[]> which returns the response + * body as a {@code byte array}. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asByteArray() { + ByteArrayResponseProcessor brp = new ByteArrayResponseProcessor(); + + return new AbstractResponseProcessor() { + + @Override + public byte[] onResponseBodyStartImpl(long contentLength, + HttpHeaders h) + throws IOException + { + brp.onStart(contentLength); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException + { + brp.onBodyContent(b); + } + + @Override + public byte[] onResponseComplete() throws IOException { + return brp.onComplete(); + } + + @Override + public void onResponseError(Throwable t) { + brp.onError(t); + } + }; + } + + /** + * Returns a response processor which decodes the body using the character + * set specified in the {@code Content-encoding} response header. If there + * is no such header, or the character set is not supported, then + * {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} is used. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asString() { + return asString(null); + } + + /** + * Returns a MultiProcessor that handles multiple responses, writes the + * response bodies to files and which returns an aggregate response object + * that is a {@code Map}. The keyset of the Map represents the + * URIs of the original request and any additional requests generated by the + * server. The values are the paths of the destination files. Each path uses + * the URI path of the request offset from the destination parent directory + * provided. + * + *

    All incoming additional requests (push promises) are accepted by this + * multi response processor. Errors are effectively ignored and any failed + * responses are simply omitted from the result Map. Other implementations + * of MultiProcessor can handle these situations + * + *

    Example usage + *

    +     * {@code
    +     *    CompletableFuture> cf =
    +     *    HttpRequest.create(new URI("https://www.foo.com/"))
    +     *               .version(Version.HTTP2)
    +     *               .GET()
    +     *               .sendAsyncMulti(HttpResponse.multiFile("/usr/destination"));
    +     *
    +     *    Map results = cf.join();
    +     * }
    +     * 
    + * + * @param destination the destination parent directory of all response + * bodies + * @return a MultiProcessor + */ + public static MultiProcessor> multiFile(Path destination) { + + return new MultiProcessor>() { + Map> bodyCFs = new HashMap<>(); + + Map results = new HashMap<>(); + + @Override + public BiFunction, Boolean> + onStart(HttpRequest mainRequest, + CompletableFuture response) { + bodyCFs.put(mainRequest.uri(), getBody(mainRequest, response)); + return (HttpRequest additional, CompletableFuture cf) -> { + CompletableFuture bcf = getBody(additional, cf); + bodyCFs.put(additional.uri(), bcf); + // we accept all comers + return true; + }; + } + + private CompletableFuture getBody(HttpRequest req, + CompletableFuture cf) { + URI u = req.uri(); + String path = u.getPath(); + return cf.thenCompose((HttpResponse resp) -> { + return resp.bodyAsync(HttpResponse.asFile(destination.resolve(path))); + }); + } + + @Override + public Map onComplete() { + // all CFs have completed normally or in error. + Set>> entries = bodyCFs.entrySet(); + for (Map.Entry> entry : entries) { + CompletableFuture v = entry.getValue(); + URI uri = entry.getKey(); + if (v.isDone() && !v.isCompletedExceptionally()) { + results.put(uri, v.join()); + } + } + return results; + } + }; + } + + /** + * Returns a {@link BodyProcessor}<{@link String}>. + * + * @param charset the name of the charset to interpret the body as. If + * {@code null} then the processor tries to determine the character set from + * the {@code Content-encoding} header. If that charset is not supported + * then {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} is + * used. + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asString(Charset charset) { + + ByteArrayResponseProcessor brp = new ByteArrayResponseProcessor(); + + return new AbstractResponseProcessor() { + Charset cs = charset; + HttpHeaders headers; + + @Override + public String onResponseBodyStartImpl(long contentLength, + HttpHeaders h) + throws IOException + { + headers = h; + brp.onStart(contentLength); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + brp.onBodyContent(b); + } + + @Override + public String onResponseComplete() throws IOException { + byte[] buf = brp.onComplete(); + if (cs == null) { + cs = headers.firstValue("Content-encoding") + .map((String s) -> Charset.forName(s)) + .orElse(StandardCharsets.ISO_8859_1); + } + return new String(buf, cs); + } + + @Override + public void onResponseError(Throwable t) { + brp.onError(t); + } + + }; + } + + /** + * Returns a response processor which ignores the response body. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor ignoreBody() { + return asByteArrayConsumer((byte[] buf) -> { /* ignore */ }); + } + + /** + * A processor for response bodies, which determines the type of the + * response body returned from {@link HttpResponse}. Response processors can + * either return an object that represents the body itself (after it has + * been read) or else an object that is used to read the body (such as an + * {@code InputStream}). The parameterized type {@code } is the type of + * the returned body object from + * {@link HttpResponse#body(BodyProcessor) HttpResponse.body} and + * (indirectly) from {@link HttpResponse#bodyAsync(BodyProcessor) + * HttpResponse.bodyAsync}. + * + *

    Implementations of this interface are provided in {@link HttpResponse} + * which write responses to {@code String, byte[], File, Consumer}. + * Custom implementations can also be used. + * + *

    The methods of this interface may be called from multiple threads, + * but only one method is invoked at a time, and behaves as if called from + * one thread. + * + * @param the type of the response body + * + * @since 9 + */ + public interface BodyProcessor { + + /** + * Called immediately before the response body is read. If {@code } + * is an object used to read or accept the response body, such as a + * {@code Consumer} or {@code InputStream} then it should be returned + * from this method, and the body object will be returned before any + * data is read. If {@code } represents the body itself after being + * read, then this method must return {@code null} and the body will be + * returned from {@link #onResponseComplete()}. In both cases, the + * actual body data is provided by the + * {@link #onResponseBodyChunk(ByteBuffer) onResponseBodyChunk} method + * in exactly the same way. + * + *

    flowController is a consumer of long values and is used for + * updating a flow control window as follows. The window represents the + * number of times + * {@link #onResponseBodyChunk(java.nio.ByteBuffer) onResponseBodyChunk} + * may be called before receiving further updates to the window. Each + * time it is called, the window is reduced by {@code 1}. When the + * window reaches zero {@code onResponseBodyChunk()} will not be called + * again until the window has opened again with further calls to + * flowController.accept(). + * {@link java.util.function.LongConsumer#accept(long) flowcontroller.accept()} + * must be called to open (increase) the window by the specified amount. + * The initial value is zero. This implies that if {@code + * onResponseBodyStart()} does not call {@code flowController.accept()} + * with a positive value no data will ever be delivered. + * + * @param contentLength {@code -1} signifies unknown content length. + * Otherwise, a positive integer, or zero. + * @param responseHeaders the response headers + * @param flowController a LongConsumer used to update the flow control + * window + * @return {@code null} or an object that can be used to read the + * response body. + * @throws IOException if an exception occurs starting the response + * body receive + */ + T onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException; + + /** + * Called if an error occurs while reading the response body. This + * terminates the operation and no further calls will occur after this. + * + * @param t the Throwable + */ + void onResponseError(Throwable t); + + /** + * Called for each buffer of data received for this response. + * ByteBuffers can be reused as soon as this method returns. + * + * @param b a ByteBuffer whose position is at the first byte that can be + * read, and whose limit is after the last byte that can be read + * @throws IOException in case of I/O error + */ + void onResponseBodyChunk(ByteBuffer b) throws IOException; + + /** + * Called after the last time + * {@link #onResponseBodyChunk(java.nio.ByteBuffer)} has been called and + * returned indicating that the entire content has been read. This + * method must return an object that represents or contains the response + * body just received, but only if an object was not returned from + * {@link #onResponseBodyStart(long, HttpHeaders, LongConsumer) + * onResponseBodyStart}. + * + * @return a T, or {@code null} if an object was already returned + * @throws IOException in case of I/O error + */ + T onResponseComplete() throws IOException; + } + + /** + * A response processor for a HTTP/2 multi response. A multi response + * comprises a main response, and zero or more additional responses. Each + * additional response is sent by the server in response to requests that + * the server also generates. Additional responses are typically resources + * that the server guesses the client will need which are related to the + * initial request. + * + *

    The server generated requests are also known as push promises. + * The server is permitted to send any number of these requests up to the + * point where the main response is fully received. Therefore, after + * completion of the main response body, the final number of additional + * responses is known. Additional responses may be cancelled, but given that + * the server does not wait for any acknowledgment before sending the + * response, this must be done quickly to avoid unnecessary data transmission. + * + *

    {@code MultiProcessor}s are parameterised with a type {@code T} which + * represents some meaningful aggregate of the responses received. This + * would typically be a Collection of response or response body objects. One + * example implementation can be found at {@link + * HttpResponse#multiFile(java.nio.file.Path)}. + * + * @param a type representing the aggregated results + * + * @since 9 + */ + public interface MultiProcessor { + + /** + * Called before or soon after a multi request is sent. The request that + * initiated the multi response is supplied, as well as a + * CompletableFuture for the main response. The implementation of this + * method must return a BiFunction which is called once for each push + * promise received. + * + *

    The parameters to the {@code BiFunction} are the {@code HttpRequest} + * for the push promise and a {@code CompletableFuture} for its + * response. The function must return a Boolean indicating whether the + * push promise has been accepted (true) or should be canceled (false). + * The CompletableFutures for any canceled pushes are themselves + * completed exceptionally soon after the function returns. + * + * @param mainRequest the main request + * @param response a CompletableFuture for the main response + * @return a BiFunction that is called for each push promise + */ + BiFunction, Boolean> + onStart(HttpRequest mainRequest, + CompletableFuture response); + + /** + * Called after all responses associated with the multi response have + * been fully processed, including response bodies. + * + *

    Example types for {@code T} could be Collections of response body + * types or {@code Map}s from request {@code URI} to a response body + * type. + * + * @return the aggregate response object + */ + T onComplete(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java new file mode 100644 index 00000000000..c71f53a04ea --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.util.concurrent.CompletableFuture; +import java.util.function.LongConsumer; +import javax.net.ssl.SSLParameters; + +/** + * The implementation class for HttpResponse + */ +class HttpResponseImpl extends HttpResponse { + + int responseCode; + Exchange exchange; + HttpRequestImpl request; + HttpHeaders1 headers; + HttpHeaders1 trailers; + SSLParameters sslParameters; + URI uri; + HttpClient.Version version; + AccessControlContext acc; + RawChannel rawchan; + HttpConnection connection; + + public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders1 headers, + HttpHeaders1 trailers, SSLParameters sslParameters, + HttpClient.Version version, HttpConnection connection) { + this.responseCode = responseCode; + this.exchange = exch; + this.request = exchange.request(); + this.headers = headers; + this.trailers = trailers; + this.sslParameters = sslParameters; + this.uri = request.uri(); + this.version = version; + this.connection = connection; + } + + @Override + public int statusCode() { + return responseCode; + } + + @Override + public HttpRequestImpl request() { + return request; + } + + @Override + public HttpHeaders headers() { + headers.makeUnmodifiable(); + return headers; + } + + @Override + public HttpHeaders trailers() { + trailers.makeUnmodifiable(); + return trailers; + } + + + @Override + public T body(java.net.http.HttpResponse.BodyProcessor processor) { + return exchange.responseBody(processor); + } + + @Override + public CompletableFuture bodyAsync(java.net.http.HttpResponse.BodyProcessor processor) { + acc = AccessController.getContext(); + return exchange.responseBodyAsync(processor); + } + + @Override + public SSLParameters sslParameters() { + return sslParameters; + } + + public AccessControlContext getAccessControlContext() { + return acc; + } + + @Override + public URI uri() { + return uri; + } + + @Override + public HttpClient.Version version() { + return version; + } + // keepalive flag determines whether connection is closed or kept alive + // by reading/skipping data + + public static java.net.http.HttpResponse.BodyProcessor ignoreBody(boolean keepalive) { + return new java.net.http.HttpResponse.BodyProcessor() { + + @Override + public Void onResponseBodyStart(long clen, HttpHeaders h, + LongConsumer flowController) throws IOException { + return null; + } + + @Override + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + } + + @Override + public Void onResponseComplete() throws IOException { + return null; + } + + @Override + public void onResponseError(Throwable t) { + } + }; + } + + /** + * + * @return + */ + RawChannel rawChannel() { + if (rawchan == null) { + rawchan = new RawChannel(request.client(), connection); + } + return rawchan; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java new file mode 100644 index 00000000000..448fda35156 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.io.IOException; + +/** + * Thrown when a response is not received within a specified time period. + */ +public class HttpTimeoutException extends IOException { + + private static final long serialVersionUID = 981344271622632951L; + + public HttpTimeoutException(String message) { + super(message); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java new file mode 100644 index 00000000000..d696854c5b5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.util.Locale; +import sun.util.logging.PlatformLogger; + +/** + * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content + * + * Any of errors, requests, headers or content are optional. + * + * Other handlers may be added. All logging is at level INFO + * + * Logger name is "java.net.http.HttpClient" + */ +class Log { + + final static String logProp = "java.net.http.HttpClient.log"; + + public static final int OFF = 0; + public static final int ERRORS = 0x1; + public static final int REQUESTS = 0x2; + public static final int HEADERS = 0x4; + public static final int CONTENT = 0x8; + public static final int FRAMES = 0x10; + public static final int SSL = 0x20; + static int logging; + + // Frame types: "control", "data", "window", "all" + public static final int CONTROL = 1; // all except DATA and WINDOW_UPDATES + public static final int DATA = 2; + public static final int WINDOW_UPDATES = 4; + public static final int ALL = CONTROL| DATA | WINDOW_UPDATES; + static int frametypes; + + static sun.util.logging.PlatformLogger logger; + + static { + String s = Utils.getNetProperty(logProp); + if (s == null) { + logging = OFF; + } else { + String[] vals = s.split(","); + for (String val : vals) { + switch (val.toLowerCase(Locale.US)) { + case "errors": + logging |= ERRORS; + break; + case "requests": + logging |= REQUESTS; + break; + case "headers": + logging |= HEADERS; + break; + case "content": + logging |= CONTENT; + break; + case "ssl": + logging |= SSL; + break; + case "all": + logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS; + break; + } + if (val.startsWith("frames")) { + logging |= FRAMES; + String[] types = val.split(":"); + if (types.length == 1) { + frametypes = CONTROL | DATA | WINDOW_UPDATES; + } else { + for (String type : types) { + switch (type.toLowerCase()) { + case "control": + frametypes |= CONTROL; + break; + case "data": + frametypes |= DATA; + break; + case "window": + frametypes |= WINDOW_UPDATES; + break; + case "all": + frametypes = ALL; + break; + } + } + } + } + } + } + if (logging != OFF) { + logger = PlatformLogger.getLogger("java.net.http.HttpClient"); + } + } + + static boolean errors() { + return (logging & ERRORS) != 0; + } + + static boolean requests() { + return (logging & REQUESTS) != 0; + } + + static boolean headers() { + return (logging & HEADERS) != 0; + } + + static boolean ssl() { + return (logging & SSL) != 0; + } + + static boolean frames() { + return (logging & FRAMES) != 0; + } + + static void logError(String s) { + if (errors()) + logger.info("ERROR: " + s); + } + + static void logError(Throwable t) { + if (errors()) { + String s = Utils.stackTrace(t); + logger.info("ERROR: " + s); + } + } + + static void logSSL(String s) { + if (ssl()) + logger.info("SSL: " + s); + } + + static void logRequest(String s) { + if (requests()) + logger.info("REQUEST: " + s); + } + + static void logResponse(String s) { + if (requests()) + logger.info("RESPONSE: " + s); + } + + static void logHeaders(String s) { + if (headers()) + logger.info("HEADERS: " + s); + } +// END HTTP2 +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java new file mode 100644 index 00000000000..8a53565ae51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.function.BiFunction; + +import static java.net.http.Pair.pair; + +/** + * Encapsulates multiple Exchanges belonging to one HttpRequestImpl. + * - manages filters + * - retries due to filters. + * - I/O errors and most other exceptions get returned directly to user + * + * Creates a new Exchange for each request/response interaction + */ +class MultiExchange { + + final HttpRequestImpl request; // the user request + final HttpClientImpl client; + HttpRequestImpl currentreq; // used for async only + Exchange exchange; // the current exchange + Exchange previous; + int attempts; + // Maximum number of times a request will be retried/redirected + // for any reason + + final static int DEFAULT_MAX_ATTEMPTS = 5; + final static int max_attempts = Utils.getIntegerNetProperty( + "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS + ); + + private final List filters; + TimedEvent td; + boolean cancelled = false; + + /** + * Filter fields. These are attached as required by filters + * and only used by the filter implementations. This could be + * generalised into Objects that are passed explicitly to the filters + * (one per MultiExchange object, and one per Exchange object possibly) + */ + volatile AuthenticationFilter.AuthInfo serverauth, proxyauth; + // RedirectHandler + volatile int numberOfRedirects = 0; + + /** + */ + MultiExchange(HttpRequestImpl request) { + this.exchange = new Exchange(request); + this.previous = null; + this.request = request; + this.currentreq = request; + this.attempts = 0; + this.client = request.client(); + this.filters = client.filterChain(); + } + + public HttpResponseImpl response() throws IOException, InterruptedException { + HttpRequestImpl r = request; + if (r.timeval() != 0) { + // set timer + td = new TimedEvent(r.timeval()); + client.registerTimer(td); + } + while (attempts < max_attempts) { + try { + attempts++; + Exchange currExchange = getExchange(); + requestFilters(r); + HttpResponseImpl response = currExchange.response(); + Pair filterResult = responseFilters(response); + HttpRequestImpl newreq = filterResult.second; + if (newreq == null) { + if (attempts > 1) { + Log.logError("Succeeded on attempt: " + attempts); + } + cancelTimer(); + return response; + } + response.body(HttpResponse.ignoreBody()); + setExchange(new Exchange(newreq, currExchange.getAccessControlContext() )); + r = newreq; + } catch (IOException e) { + if (cancelled) { + throw new HttpTimeoutException("Request timed out"); + } + throw e; + } + } + cancelTimer(); + throw new IOException("Retry limit exceeded"); + } + + private synchronized Exchange getExchange() { + return exchange; + } + + private synchronized void setExchange(Exchange exchange) { + this.exchange = exchange; + } + + private void cancelTimer() { + if (td != null) { + client.cancelTimer(td); + } + } + + private void requestFilters(HttpRequestImpl r) throws IOException { + for (HeaderFilter filter : filters) { + filter.request(r); + } + } + + // Filters are assumed to be non-blocking so the async + // versions of these methods just call the blocking ones + + private CompletableFuture requestFiltersAsync(HttpRequestImpl r) { + CompletableFuture cf = new CompletableFuture<>(); + try { + requestFilters(r); + cf.complete(null); + } catch(Throwable e) { + cf.completeExceptionally(e); + } + return cf; + } + + + private Pair + responseFilters(HttpResponse response) throws IOException + { + for (HeaderFilter filter : filters) { + HttpRequestImpl newreq = filter.response((HttpResponseImpl)response); + if (newreq != null) { + return pair(null, newreq); + } + } + return pair(response, null); + } + + private CompletableFuture> + responseFiltersAsync(HttpResponse response) + { + CompletableFuture> cf = new CompletableFuture<>(); + try { + Pair n = responseFilters(response); // assumed to be fast + cf.complete(n); + } catch (Throwable e) { + cf.completeExceptionally(e); + } + return cf; + } + + public void cancel() { + cancelled = true; + getExchange().cancel(); + } + + public CompletableFuture responseAsync(Void v) { + CompletableFuture cf; + if (++attempts > max_attempts) { + cf = new CompletableFuture<>(); + cf.completeExceptionally(new IOException("Too many retries")); + } else { + if (currentreq.timeval() != 0) { + // set timer + td = new TimedEvent(currentreq.timeval()); + client.registerTimer(td); + } + Exchange exch = getExchange(); + cf = requestFiltersAsync(currentreq) + .thenCompose(exch::responseAsync) + .thenCompose(this::responseFiltersAsync) + .thenCompose((Pair pair) -> { + HttpResponseImpl resp = (HttpResponseImpl)pair.first; + if (resp != null) { + if (attempts > 1) { + Log.logError("Succeeded on attempt: " + attempts); + } + return CompletableFuture.completedFuture(resp); + } else { + currentreq = pair.second; + Exchange previous = exch; + setExchange(new Exchange(currentreq, + currentreq.getAccessControlContext())); + //reads body off previous, and then waits for next response + return previous + .responseBodyAsync(HttpResponse.ignoreBody()) + .thenCompose(this::responseAsync); + } + }) + .handle((BiFunction>) Pair::new) + .thenCompose((Pair obj) -> { + HttpResponseImpl response = (HttpResponseImpl)obj.first; + if (response != null) { + return CompletableFuture.completedFuture(response); + } + // all exceptions thrown are handled here + CompletableFuture error = getExceptionalCF(obj.second); + if (error == null) { + cancelTimer(); + return responseAsync(null); + } else { + return error; + } + }); + } + return cf; + } + + /** + * Take a Throwable and return a suitable CompletableFuture that is + * completed exceptionally. + */ + private CompletableFuture getExceptionalCF(Throwable t) { + CompletableFuture error = new CompletableFuture<>(); + if ((t instanceof CompletionException) || (t instanceof ExecutionException)) { + if (t.getCause() != null) { + t = t.getCause(); + } + } + if (cancelled && t instanceof IOException) { + t = new HttpTimeoutException("request timed out"); + } + error.completeExceptionally(t); + return error; + } + + T responseBody(HttpResponse.BodyProcessor processor) { + return getExchange().responseBody(processor); + } + + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return getExchange().responseBodyAsync(processor); + } + + class TimedEvent extends TimeoutEvent { + TimedEvent(long timeval) { + super(timeval); + } + @Override + public void handle() { + cancel(); + } + + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java new file mode 100644 index 00000000000..5ffeaf6c961 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. + * 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 License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 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 License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.net.http; + +/** + * A simple paired value class + */ +final class Pair { + + Pair(T first, U second) { + this.second = second; + this.first = first; + } + + final T first; + final U second; + + // Because 'pair()' is shorter than 'new Pair<>()'. + // Sometimes this difference might be very significant (especially in a + // 80-ish characters boundary). Sorry diamond operator. + static Pair pair(T first, U second) { + return new Pair<>(first, second); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java new file mode 100644 index 00000000000..e206f9204e2 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; + +/** + * Plain raw TCP connection direct to destination + */ +class PlainHttpConnection extends HttpConnection { + + protected SocketChannel chan; + private volatile boolean connected; + private boolean closed; + + class ConnectEvent extends AsyncEvent implements AsyncEvent.Blocking { + CompletableFuture cf; + + ConnectEvent(CompletableFuture cf) { + this.cf = cf; + } + + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public int interestOps() { + return SelectionKey.OP_CONNECT; + } + + @Override + public void handle() { + try { + chan.finishConnect(); + } catch (IOException e) { + cf.completeExceptionally(e); + } + connected = true; + cf.complete(null); + } + + @Override + public void abort() { + close(); + } + } + + @Override + public CompletableFuture connectAsync() { + CompletableFuture plainFuture = new CompletableFuture<>(); + try { + chan.configureBlocking(false); + chan.connect(address); + client.registerEvent(new ConnectEvent(plainFuture)); + } catch (IOException e) { + plainFuture.completeExceptionally(e); + } + return plainFuture; + } + + @Override + public void connect() throws IOException { + chan.connect(address); + connected = true; + } + + @Override + SocketChannel channel() { + return chan; + } + + PlainHttpConnection(InetSocketAddress addr, HttpClientImpl client) { + super(addr, client); + try { + this.chan = SocketChannel.open(); + int bufsize = client.getReceiveBufferSize(); + chan.setOption(StandardSocketOptions.SO_RCVBUF, bufsize); + } catch (IOException e) { + throw new InternalError(e); + } + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + //debugPrint("Send", buffers, start, number); + return chan.write(buffers, start, number); + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + return chan.write(buffer); + } + + @Override + public String toString() { + return "PlainHttpConnection: " + super.toString(); + } + + /** + * Close this connection + */ + @Override + synchronized void close() { + if (closed) + return; + closed = true; + try { + Log.logError("Closing: " + toString()); + //System.out.println("Closing: " + this); + chan.close(); + } catch (IOException e) {} + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = getBuffer(); // TODO not using length + int n = chan.read(buf); + if (n == -1) { + return null; + } + buf.flip(); + String s = "Receive (" + n + " bytes) "; + //debugPrint(s, buf); + return buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + int mark = buf.position(); + int n = chan.read(buf); + if (n == -1) { + return -1; + } + Utils.flipToMark(buffer, mark); + String s = "Receive (" + n + " bytes) "; + //debugPrint(s, buf); + return n; + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(address, null); + } + + @Override + synchronized boolean connected() { + return connected; + } + + class ReceiveResponseEvent extends AsyncEvent implements AsyncEvent.Blocking { + CompletableFuture cf; + + ReceiveResponseEvent(CompletableFuture cf) { + this.cf = cf; + } + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public void handle() { + cf.complete(null); + } + + @Override + public int interestOps() { + return SelectionKey.OP_READ; + } + + @Override + public void abort() { + close(); + } + } + + @Override + boolean isSecure() { + return false; + } + + @Override + boolean isProxied() { + return false; + } + + @Override + CompletableFuture whenReceivingResponse() { + CompletableFuture cf = new CompletableFuture<>(); + try { + client.registerEvent(new ReceiveResponseEvent(cf)); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java new file mode 100644 index 00000000000..1e1170ad184 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.net.InetSocketAddress; + +class PlainProxyConnection extends PlainHttpConnection { + + PlainProxyConnection(InetSocketAddress proxy, HttpClientImpl client) { + super(proxy, client); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(null, address); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java new file mode 100644 index 00000000000..2042baa2c4e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.security.AccessControlContext; +import java.util.concurrent.CompletableFuture; + +/** + * A plain text socket tunnel through a proxy. Uses "CONNECT" but does not + * encrypt. Used by WebSockets. Subclassed in SSLTunnelConnection for encryption. + */ +class PlainTunnelingConnection extends HttpConnection { + + final PlainHttpConnection delegate; + protected final InetSocketAddress proxyAddr; + private volatile boolean connected; + private final AccessControlContext acc; + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenCompose((Void v) -> { + HttpRequestImpl req = new HttpRequestImpl(client, "CONNECT", address); + Exchange connectExchange = new Exchange(req, acc); + return connectExchange + .responseAsyncImpl(delegate) + .thenCompose((HttpResponse r) -> { + CompletableFuture cf = new CompletableFuture<>(); + if (r.statusCode() != 200) { + cf.completeExceptionally(new IOException("Tunnel failed")); + } else { + connected = true; + cf.complete(null); + } + return cf; + }); + }); + } + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + HttpRequestImpl req = new HttpRequestImpl(client, "CONNECT", address); + Exchange connectExchange = new Exchange(req, acc); + HttpResponse r = connectExchange.responseImpl(delegate); + if (r.statusCode() != 200) { + throw new IOException("Tunnel failed"); + } + connected = true; + } + + @Override + boolean connected() { + return connected; + } + + protected PlainTunnelingConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpClientImpl client, + AccessControlContext acc) { + super(addr, client); + this.proxyAddr = proxy; + this.acc = acc; + delegate = new PlainHttpConnection(proxy, client); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(null, proxyAddr); + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + return delegate.write(buffers, start, number); + } + + @Override + long write(ByteBuffer buffer) throws IOException { + return delegate.write(buffer); + } + + @Override + void close() { + delegate.close(); + connected = false; + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + return delegate.readImpl(length); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + protected int readImpl(ByteBuffer buffer) throws IOException { + return delegate.readImpl(buffer); + } + + @Override + boolean isSecure() { + return false; + } + + @Override + boolean isProxied() { + return true; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java new file mode 100644 index 00000000000..9566eeb555c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.SelectableChannel; + +/** + * Used to implement WebSocket. Each RawChannel corresponds to + * a TCP connection (SocketChannel) but is connected to a Selector + * and an ExecutorService for invoking the send and receive callbacks + * Also includes SSL processing. + */ +class RawChannel implements ByteChannel, GatheringByteChannel { + + private final HttpClientImpl client; + private final HttpConnection connection; + private boolean closed; + + private interface RawEvent { + + /** must return the selector interest op flags OR'd. */ + int interestOps(); + + /** called when event occurs. */ + void handle(); + } + + interface BlockingEvent extends RawEvent { } + + interface NonBlockingEvent extends RawEvent { } + + RawChannel(HttpClientImpl client, HttpConnection connection) { + this.client = client; + this.connection = connection; + } + + private class RawAsyncEvent extends AsyncEvent { + + private final RawEvent re; + + RawAsyncEvent(RawEvent re) { + this.re = re; + } + + public SelectableChannel channel() { + return connection.channel(); + } + + // must return the selector interest op flags OR'd + public int interestOps() { + return re.interestOps(); + } + + // called when event occurs + public void handle() { + re.handle(); + } + + public void abort() {} + } + + private class BlockingRawAsyncEvent extends RawAsyncEvent + implements AsyncEvent.Blocking { + + BlockingRawAsyncEvent(RawEvent re) { + super(re); + } + } + + private class NonBlockingRawAsyncEvent extends RawAsyncEvent + implements AsyncEvent.NonBlocking { + + NonBlockingRawAsyncEvent(RawEvent re) { + super(re); + } + } + + /* + * Register given event whose callback will be called once only. + * (i.e. register new event for each callback) + */ + public void registerEvent(RawEvent event) throws IOException { + if (event instanceof BlockingEvent) { + client.registerEvent(new BlockingRawAsyncEvent(event)); + } else if (event instanceof NonBlockingEvent) { + client.registerEvent(new NonBlockingRawAsyncEvent(event)); + } else { + throw new InternalError(); + } + } + + @Override + public int read(ByteBuffer dst) throws IOException { + return connection.read(dst); + } + + @Override + public boolean isOpen() { + return !closed; + } + + @Override + public void close() throws IOException { + closed = true; + connection.close(); + } + + @Override + public long write(ByteBuffer[] src) throws IOException { + return connection.write(src, 0, src.length); + } + + @Override + public long write(ByteBuffer[] src, int offset, int len) + throws IOException { + return connection.write(src, offset, len); + } + + @Override + public int write(ByteBuffer src) throws IOException { + return (int) connection.write(src); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java new file mode 100644 index 00000000000..3c3be4d17c5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; + +class RedirectFilter implements HeaderFilter { + + HttpRequestImpl requestImpl; + HttpRequest request; + HttpClientImpl client; + String method; + final static int DEFAULT_MAX_REDIRECTS = 5; + URI uri; + + final static int max_redirects = Utils.getIntegerNetProperty( + "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS + ); + + @Override + public void request(HttpRequestImpl r) throws IOException { + this.request = r; + this.client = r.getClient(); + this.method = r.method(); + this.requestImpl = r; + this.uri = r.uri(); + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + return handleResponse(r); + } + + /** + * checks to see if new request needed and returns it. + * Null means response is ok to return to user. + */ + private HttpRequestImpl handleResponse(HttpResponseImpl r) { + int rcode = r.statusCode(); + if (rcode == 200) { + return null; + } + if (rcode >= 300 && rcode <= 399) { + URI redir = getRedirectedURI(r.headers()); + if (canRedirect(r) && ++r.request.exchange.numberOfRedirects < max_redirects) { + //System.out.println("Redirecting to: " + redir); + return new HttpRequestImpl(redir, request, client, method, requestImpl); + } else { + //System.out.println("Redirect: giving up"); + return null; + } + } + return null; + } + + private URI getRedirectedURI(HttpHeaders headers) { + URI redirectedURI; + redirectedURI = headers.firstValue("Location") + .map((s) -> URI.create(s)) + .orElseThrow(() -> new UncheckedIOException( + new IOException("Invalid redirection"))); + + // redirect could be relative to original URL, but if not + // then redirect is used. + redirectedURI = uri.resolve(redirectedURI); + return redirectedURI; + } + + private boolean canRedirect(HttpResponse r) { + return requestImpl.followRedirectsImpl().redirect(r); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java new file mode 100644 index 00000000000..f6e8d7504d9 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Implements chunked/fixed transfer encodings of HTTP/1.1 responses. + */ +class ResponseContent { + + final HttpResponse.BodyProcessor userProcessor; + final HttpResponse.BodyProcessor pusher; + final HttpConnection connection; + final int contentLength; + ByteBuffer buffer; + ByteBuffer lastBufferUsed; + final ResponseHeaders headers; + final Http1Response.FlowController flowController; + + ResponseContent(HttpConnection connection, + int contentLength, + ResponseHeaders h, + HttpResponse.BodyProcessor userProcessor, + Http1Response.FlowController flowController) { + this.userProcessor = userProcessor; + this.pusher = (HttpResponse.BodyProcessor)userProcessor; + this.connection = connection; + this.contentLength = contentLength; + this.headers = h; + this.flowController = flowController; + } + + static final int LF = 10; + static final int CR = 13; + static final int SP = 0x20; + static final int BUF_SIZE = 1024; + + boolean chunkedContent, chunkedContentInitialized; + + private boolean contentChunked() throws IOException { + if (chunkedContentInitialized) { + return chunkedContent; + } + if (contentLength == -1) { + String tc = headers.firstValue("Transfer-Encoding") + .orElse(""); + if (!tc.equals("")) { + if (tc.equalsIgnoreCase("chunked")) { + chunkedContent = true; + } else { + throw new IOException("invalid content"); + } + } else { + chunkedContent = false; + } + } + chunkedContentInitialized = true; + return chunkedContent; + } + + /** + * Entry point for pusher. b is an initial ByteBuffer that may + * have some data in it. When this method returns, the body + * has been fully processed. + */ + void pushBody(ByteBuffer b) throws IOException { + // TODO: check status + if (contentChunked()) { + pushBodyChunked(b); + } else { + pushBodyFixed(b); + } + } + + // reads and returns chunklen. Position of chunkbuf is first byte + // of chunk on return. chunklen includes the CR LF at end of chunk + int readChunkLen() throws IOException { + chunklen = 0; + boolean cr = false; + while (true) { + getHunk(); + int c = chunkbuf.get(); + if (cr) { + if (c == LF) { + return chunklen + 2; + } else { + throw new IOException("invalid chunk header"); + } + } + if (c == CR) { + cr = true; + } else { + int digit = toDigit(c); + chunklen = chunklen * 16 + digit; + } + } + } + + int chunklen = -1; // number of bytes in chunk (fixed) + int bytesremaining; // number of bytes in chunk left to be read incl CRLF + int bytesread; + ByteBuffer chunkbuf; // initialise + + // make sure we have at least 1 byte to look at + private void getHunk() throws IOException { + while (chunkbuf == null || !chunkbuf.hasRemaining()) { + + if (chunkbuf != null) { + connection.returnBuffer(chunkbuf); + } + chunkbuf = connection.read(); + } + } + + private void consumeBytes(int n) throws IOException { + getHunk(); + while (n > 0) { + int e = Math.min(chunkbuf.remaining(), n); + chunkbuf.position(chunkbuf.position() + e); + n -= e; + if (n > 0) + getHunk(); + } + } + + /** + * Returns a ByteBuffer containing a chunk of data or a "hunk" of data + * (a chunk of a chunk if the chunk size is larger than our ByteBuffers). + */ + ByteBuffer readChunkedBuffer() throws IOException { + if (chunklen == -1) { + // new chunk + bytesremaining = readChunkLen(); + chunklen = bytesremaining - 2; + if (chunklen == 0) { + consumeBytes(2); + return null; + } + } + + getHunk(); + bytesread = chunkbuf.remaining(); + ByteBuffer returnBuffer; + + /** + * Cases. Always at least one byte is read by getHunk() + * + * 1) one read contains exactly 1 chunk. Strip off CRLF and pass buffer on + * 2) one read contains a hunk. If at end of chunk, consume CRLF.Pass buffer up. + * 3) read contains rest of chunk and more data. Copy buffer. + */ + if (bytesread == bytesremaining) { + // common case: 1 read = 1 chunk (or final hunk of chunk) + chunkbuf.limit(chunkbuf.limit() - 2); // remove trailing CRLF + bytesremaining = 0; + returnBuffer = chunkbuf; + chunkbuf = null; + chunklen = -1; + } else if (bytesread < bytesremaining) { + // read a hunk, maybe including CR or LF or both + bytesremaining -= bytesread; + if (bytesremaining <= 2) { + // remove any trailing CR LF already read, and then read the rest + chunkbuf.limit(chunkbuf.limit() - (2 - bytesremaining)); + consumeBytes(bytesremaining); + chunklen = -1; + } + returnBuffer = chunkbuf; + chunkbuf = null; + } else { + // bytesread > bytesremaining + returnBuffer = splitChunkedBuffer(bytesremaining-2); + bytesremaining = 0; + chunklen = -1; + consumeBytes(2); + } + return returnBuffer; + } + + ByteBuffer initialBuffer; + int fixedBytesReturned; + + ByteBuffer getResidue() { + return lastBufferUsed; + } + + private void compactBuffer(ByteBuffer buf) { + buf.compact() + .flip(); + } + + /** + * Copies inbuf (numBytes from its position) to new buffer. The returned + * buffer's position is zero and limit is at end (numBytes) + */ + private ByteBuffer copyBuffer(ByteBuffer inbuf, int numBytes) { + ByteBuffer b1 = connection.getBuffer(); + assert b1.remaining() >= numBytes; + byte[] b = b1.array(); + inbuf.get(b, 0, numBytes); + b1.limit(numBytes); + return b1; + } + + /** + * Split numBytes of data out of chunkbuf from the remainder, + * copying whichever part is smaller. chunkbuf points to second part + * of buffer on return. The returned buffer is the data from position + * to position + numBytes. Both buffers positions are reset so same + * data can be re-read. + */ + private ByteBuffer splitChunkedBuffer(int numBytes) { + ByteBuffer newbuf = connection.getBuffer(); + byte[] b = newbuf.array(); + int midpoint = chunkbuf.position() + numBytes; + int remainder = chunkbuf.limit() - midpoint; + + if (numBytes < remainder) { + // copy first part of chunkbuf to new buf + chunkbuf.get(b, 0, numBytes); + newbuf.limit(numBytes); + return newbuf; + } else { + // copy remainder of chunkbuf to newbuf and make newbuf chunkbuf + chunkbuf.mark(); + chunkbuf.position(midpoint); + chunkbuf.get(b, 0, remainder); + chunkbuf.reset(); + chunkbuf.limit(midpoint); + newbuf.limit(remainder); + newbuf.position(0); + ByteBuffer tmp = chunkbuf; + chunkbuf = newbuf; + return tmp; + } + } + + private void pushBodyChunked(ByteBuffer b) throws IOException { + chunkbuf = b; + while (true) { + ByteBuffer b1 = readChunkedBuffer(); + if (b1 != null) { + if (b1.hasRemaining()) { + request(1); // wait till we can send + pusher.onResponseBodyChunk(b1); + lastBufferUsed = b1; + } + } else { + return; + } + } + } + + private int toDigit(int b) throws IOException { + if (b >= 0x30 && b <= 0x39) { + return b - 0x30; + } + if (b >= 0x41 && b <= 0x46) { + return b - 0x41 + 10; + } + if (b >= 0x61 && b <= 0x66) { + return b - 0x61 + 10; + } + throw new IOException("Invalid chunk header byte " + b); + } + + private void request(long value) throws IOException { + try { + flowController.request(value); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + + private void pushBodyFixed(ByteBuffer b) throws IOException { + lastBufferUsed = b; + for (int remaining = contentLength; remaining > 0;) { + int bufsize = b.remaining(); + if (bufsize > remaining) { + // more data available than required, must copy + lastBufferUsed = b; + b = copyBuffer(b, remaining); + remaining = 0; + } else { + // pass entire buffer up to user + remaining -= bufsize; + compactBuffer(b); + } + request(1); // wait till we can send + pusher.onResponseBodyChunk(b); + if (remaining > 0) { + b = connection.read(); + if (b == null) { + throw new IOException("Error reading response"); + } + lastBufferUsed = b; + } + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java new file mode 100644 index 00000000000..b378e784c51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Reads response headers off channel, in blocking mode. Entire header + * block is collected in a byte[]. The offset location of the start of + * each header name is recorded in an array to facilitate later searching. + * + * The location of "Content-length" is recorded explicitly. Similar approach + * could be taken for other common headers. + * + * This class is not thread-safe + */ +class ResponseHeaders implements HttpHeaders1 { + + static final int DATA_SIZE = 16 * 1024; // initial space for headers + static final int NUM_HEADERS = 50; // initial expected max number of headers + + final HttpConnection connection; + byte[] data; + int contentlen = -2; // means not initialized + ByteBuffer buffer; + + /** + * Following used for scanning the array looking for: + * - well known headers + * - end of header block + */ + int[] headerOffsets; // index into data + int numHeaders; + int count; + + ByteBuffer residue; // after headers processed, data may be here + + ResponseHeaders(HttpConnection connection, ByteBuffer buffer) { + this.connection = connection; + initOffsets(); + this.buffer = buffer; + data = new byte[DATA_SIZE]; + } + + int getContentLength() throws IOException { + if (contentlen != -2) { + return contentlen; + } + int[] search = findHeaderValue("Content-length"); + if (search[0] == -1) { + contentlen = -1; + return -1; + } + + int i = search[0]; + + while (data[i] == ' ' || data[i] == '\t') { + i++; + if (i == data.length || data[i] == CR || data[i] == LF) { + throw new IOException("Bad header"); + } + } + contentlen = 0; + int digit = data[i++] - 0x30; + while (digit >= 0 && digit <= 9) { + contentlen = contentlen * 10 + digit; + digit = data[i++] - 0x30; + } + return contentlen; + } + + void log() { + populateMap(false); + } + + void populateMap(boolean clearOffsets) { + StringBuilder sb; + + for (int i = 0; i < numHeaders; i++) { + sb = new StringBuilder(32); + int offset = headerOffsets[i]; + if (offset == -1) { + continue; + } + int j; + for (j=0; data[offset+j] != ':'; j++) { + // byte to char promotion ok for US-ASCII + sb.append((char)data[offset+j]); + } + String name = sb.toString(); + List l = getOrCreate(name); + addEntry(l, name, offset + j + 1); + // clear the offset + if (clearOffsets) + headerOffsets[i] = -1; + } + } + + void addEntry(List l, String name, int j) { + + while (data[j] == ' ' || data[j] == '\t') { + j++; + } + + int vstart = j; + // TODO: back slash ?? + + while (data[j] != CR) { + j++; + } + try { + String value = new String(data, vstart, j - vstart, "US-ASCII"); + l.add(value); + } catch (UnsupportedEncodingException e) { + // can't happen + throw new InternalError(e); + } + } + + // returns an int[2]: [0] = offset of value in data[] + // [1] = offset in headerOffsets. Both are -1 in error + + private int[] findHeaderValue(String name) { + int[] result = new int[2]; + byte[] namebytes = getBytes(name); + + outer: for (int i = 0; i < numHeaders; i++) { + int offset = headerOffsets[i]; + if (offset == -1) { + continue; + } + + for (int j=0; j populateMapEntry(String name) { + List l = getOrCreate(name); + int[] search = findHeaderValue(name); + if (search[0] != -1) { + addEntry(l, name, search[0]); + // clear the offset + headerOffsets[search[1]] = -1; + } + return l; + } + + static final Locale usLocale = Locale.US; + static final Charset ascii = StandardCharsets.US_ASCII; + + private byte[] getBytes(String name) { + return name.toLowerCase(usLocale).getBytes(ascii); + } + + /* + * We read buffers in a loop until we detect end of headers + * CRLFCRLF. Each byte received is copied into the byte[] data + * The position of the first byte of each header (after a CRLF) + * is recorded in a separate array showing the location of + * each header name. + */ + void initHeaders() throws IOException { + + inHeaderName = true; + endOfHeader = true; + + for (int numBuffers = 0; true; numBuffers++) { + + if (numBuffers > 0) { + buffer = connection.read(); + } + + if (buffer == null) { + throw new IOException("Error reading headers"); + } + + if (!buffer.hasRemaining()) { + continue; + } + + // Position set to first byte + int start = buffer.position(); + byte[] backing = buffer.array(); + int len = buffer.limit() - start; + + for (int i = 0; i < len; i++) { + byte b = backing[i + start]; + if (inHeaderName) { + b = lowerCase(b); + } + if (b == ':') { + inHeaderName = false; + } + data[count++] = b; + checkByte(b); + if (firstChar) { + recordHeaderOffset(count-1); + firstChar = false; + } + if (endOfHeader && numHeaders == 0) { + // empty headers + endOfAllHeaders = true; + } + if (endOfAllHeaders) { + int newposition = i + 1 + start; + if (newposition <= buffer.limit()) { + buffer.position(newposition); + residue = buffer; + } else { + residue = null; + } + return; + } + + if (count == data.length) { + resizeData(); + } + } + } + } + + static final int CR = 13; + static final int LF = 10; + int crlfCount = 0; + + // results of checkByte() + boolean endOfHeader; // just seen LF after CR before + boolean endOfAllHeaders; // just seen LF after CRLFCR before + boolean firstChar; // + boolean inHeaderName; // examining header name + + void checkByte(byte b) throws IOException { + if (endOfHeader && b != CR && b != LF) + firstChar = true; + endOfHeader = false; + endOfAllHeaders = false; + switch (crlfCount) { + case 0: + crlfCount = b == CR ? 1 : 0; + break; + case 1: + crlfCount = b == LF ? 2 : 0; + endOfHeader = true; + inHeaderName = true; + break; + case 2: + crlfCount = b == CR ? 3 : 0; + break; + case 3: + if (b != LF) { + throw new IOException("Bad header block termination"); + } + endOfAllHeaders = true; + break; + } + } + + byte lowerCase(byte b) { + if (b >= 0x41 && b <= 0x5A) + b = (byte)(b + 32); + return b; + } + + void resizeData() { + int oldlen = data.length; + int newlen = oldlen * 2; + byte[] newdata = new byte[newlen]; + System.arraycopy(data, 0, newdata, 0, oldlen); + data = newdata; + } + + final void initOffsets() { + headerOffsets = new int[NUM_HEADERS]; + numHeaders = 0; + } + + ByteBuffer getResidue() { + return residue; + } + + void recordHeaderOffset(int index) { + if (numHeaders >= headerOffsets.length) { + int oldlen = headerOffsets.length; + int newlen = oldlen * 2; + int[] new1 = new int[newlen]; + System.arraycopy(headerOffsets, 0, new1, 0, oldlen); + headerOffsets = new1; + } + headerOffsets[numHeaders++] = index; + } + + /** + * As entries are read from the byte[] they are placed in here + * So we always check this map first + */ + Map> headers = new HashMap<>(); + + @Override + public Optional firstValue(String name) { + List l = allValues(name); + if (l == null || l.isEmpty()) { + return Optional.ofNullable(null); + } else { + return Optional.of(l.get(0)); + } + } + + @Override + public List allValues(String name) { + name = name.toLowerCase(usLocale); + List l = headers.get(name); + if (l == null) { + l = populateMapEntry(name); + } + return Collections.unmodifiableList(l); + } + + @Override + public void makeUnmodifiable() { + } + + // Delegates map to HashMap but converts keys to lower case + + static class HeaderMap implements Map> { + Map> inner; + + HeaderMap(Map> inner) { + this.inner = inner; + } + @Override + public int size() { + return inner.size(); + } + + @Override + public boolean isEmpty() { + return inner.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + if (!(key instanceof String)) { + return false; + } + String s = ((String)key).toLowerCase(usLocale); + return inner.containsKey(s); + } + + @Override + public boolean containsValue(Object value) { + return inner.containsValue(value); + } + + @Override + public List get(Object key) { + String s = ((String)key).toLowerCase(usLocale); + return inner.get(s); + } + + @Override + public List put(String key, List value) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public List remove(Object key) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void putAll(Map> m) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void clear() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public Set keySet() { + return inner.keySet(); + } + + @Override + public Collection> values() { + return inner.values(); + } + + @Override + public Set>> entrySet() { + return inner.entrySet(); + } + } + + @Override + public Map> map() { + populateMap(true); + return new HeaderMap(headers); + } + + Map> mapInternal() { + populateMap(false); + return new HeaderMap(headers); + } + + private List getOrCreate(String name) { + List l = headers.get(name); + if (l == null) { + l = new LinkedList<>(); + headers.put(name, l); + } + return l; + } + + @Override + public Optional firstValueAsLong(String name) { + List l = allValues(name); + if (l == null) { + return Optional.ofNullable(null); + } else { + String v = l.get(0); + Long lv = Long.parseLong(v); + return Optional.of(lv); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java new file mode 100644 index 00000000000..4b8cb3c0516 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import java.net.http.SSLDelegate.BufType; +import java.net.http.SSLDelegate.WrapperResult; + +/** + * An SSL connection built on a Plain TCP connection. + */ +class SSLConnection extends HttpConnection { + + PlainHttpConnection delegate; + SSLDelegate sslDelegate; + final String[] alpn; + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenCompose((Void v) -> { + CompletableFuture cf = new CompletableFuture<>(); + try { + this.sslDelegate = new SSLDelegate(delegate.channel(), + client, + alpn); + cf.complete(null); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + }); + } + + @Override + public void connect() throws IOException { + delegate.connect(); + this.sslDelegate = new SSLDelegate(delegate.channel(), client, alpn); + } + + SSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) { + super(addr, client); + this.alpn = ap; + delegate = new PlainHttpConnection(addr, client); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "SSLConnection: " + super.toString(); + } + + private static long countBytes(ByteBuffer[] buffers, int start, int length) { + long c = 0; + for (int i=0; i 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long l = buffer.remaining(); + WrapperResult r = sslDelegate.sendData(buffer); + if (r.result.getStatus() == Status.CLOSED) { + if (l > 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + void close() { + try { + //System.err.println ("Closing: " + this); + delegate.channel().close(); // TODO: proper close + } catch (IOException ex) { + Log.logError(ex.toString()); + } + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length); + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + // TODO: need to ensure that buf is big enough for application data + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.result.bytesProduced(); + } + + @Override + boolean connected() { + return delegate.connected(); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return false; + } + +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java new file mode 100644 index 00000000000..fbc0674513c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.Arrays; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; +import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; + +/** + * Implements the mechanics of SSL by managing an SSLEngine object. + * One of these is associated with each SSLConnection. + */ +class SSLDelegate { + + final SSLEngine engine; + final EngineWrapper wrapper; + final Lock handshaking = new ReentrantLock(); + final SSLParameters sslParameters; + final SocketChannel chan; + final HttpClientImpl client; + + // alpn[] may be null + SSLDelegate(SocketChannel chan, HttpClientImpl client, String[] alpn) + throws IOException + { + SSLContext context = client.sslContext(); + engine = context.createSSLEngine(); + engine.setUseClientMode(true); + SSLParameters sslp = client.sslParameters().orElse(null); + if (sslp == null) { + sslp = context.getDefaultSSLParameters(); + } + sslParameters = Utils.copySSLParameters(sslp); + if (alpn != null) { + sslParameters.setApplicationProtocols(alpn); + Log.logSSL("Setting application protocols: " + Arrays.toString(alpn)); + } else { + Log.logSSL("Warning no application protocols proposed!"); + } + engine.setSSLParameters(sslParameters); + wrapper = new EngineWrapper(chan, engine); + this.chan = chan; + this.client = client; + } + + SSLParameters getSSLParameters() { + return sslParameters; + } + + private static long countBytes(ByteBuffer[] buffers, int start, int number) { + long c = 0; + for (int i=0; i packet_buf_size) { + packet_buf_size = len; + } + size = packet_buf_size; + } else { + if (app_buf_size == 0) { + SSLSession sess = engine.getSession(); + app_buf_size = sess.getApplicationBufferSize(); + } + if (len > app_buf_size) { + app_buf_size = len; + } + size = app_buf_size; + } + return ByteBuffer.allocate (size); + } + } + + /* reallocates the buffer by :- + * 1. creating a new buffer double the size of the old one + * 2. putting the contents of the old buffer into the new one + * 3. set xx_buf_size to the new size if it was smaller than new size + * + * flip is set to true if the old buffer needs to be flipped + * before it is copied. + */ + private ByteBuffer realloc (ByteBuffer b, boolean flip, BufType type) { + synchronized (this) { + int nsize = 2 * b.capacity(); + ByteBuffer n = allocate (type, nsize); + if (flip) { + b.flip(); + } + n.put(b); + b = n; + } + return b; + } + + /** + * This is a thin wrapper over SSLEngine and the SocketChannel, which + * guarantees the ordering of wraps/unwraps with respect to the underlying + * channel read/writes. It handles the UNDER/OVERFLOW status codes + * It does not handle the handshaking status codes, or the CLOSED status code + * though once the engine is closed, any attempt to read/write to it + * will get an exception. The overall result is returned. + * It functions synchronously/blocking + */ + class EngineWrapper { + + SocketChannel chan; + SSLEngine engine; + Object wrapLock, unwrapLock; + ByteBuffer unwrap_src, wrap_dst; + boolean closed = false; + int u_remaining; // the number of bytes left in unwrap_src after an unwrap() + + EngineWrapper (SocketChannel chan, SSLEngine engine) throws IOException { + this.chan = chan; + this.engine = engine; + wrapLock = new Object(); + unwrapLock = new Object(); + unwrap_src = allocate(BufType.PACKET); + wrap_dst = allocate(BufType.PACKET); + } + + void close () throws IOException { + } + + WrapperResult wrapAndSend(ByteBuffer src, boolean ignoreClose) + throws IOException + { + ByteBuffer[] buffers = new ByteBuffer[1]; + buffers[0] = src; + return wrapAndSend(buffers, 0, 1, ignoreClose); + } + + /* try to wrap and send the data in src. Handles OVERFLOW. + * Might block if there is an outbound blockage or if another + * thread is calling wrap(). Also, might not send any data + * if an unwrap is needed. + */ + WrapperResult wrapAndSend(ByteBuffer[] src, + int offset, + int len, + boolean ignoreClose) + throws IOException + { + if (closed && !ignoreClose) { + throw new IOException ("Engine is closed"); + } + Status status; + WrapperResult r = new WrapperResult(); + synchronized (wrapLock) { + wrap_dst.clear(); + do { + r.result = engine.wrap (src, offset, len, wrap_dst); + status = r.result.getStatus(); + if (status == Status.BUFFER_OVERFLOW) { + wrap_dst = realloc (wrap_dst, true, BufType.PACKET); + } + } while (status == Status.BUFFER_OVERFLOW); + if (status == Status.CLOSED && !ignoreClose) { + closed = true; + return r; + } + if (r.result.bytesProduced() > 0) { + wrap_dst.flip(); + int l = wrap_dst.remaining(); + assert l == r.result.bytesProduced(); + while (l>0) { + l -= chan.write (wrap_dst); + } + } + } + return r; + } + + /* block until a complete message is available and return it + * in dst, together with the Result. dst may have been re-allocated + * so caller should check the returned value in Result + * If handshaking is in progress then, possibly no data is returned + */ + WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException { + Status status; + WrapperResult r = new WrapperResult(); + r.buf = dst; + if (closed) { + throw new IOException ("Engine is closed"); + } + boolean needData; + if (u_remaining > 0) { + unwrap_src.compact(); + unwrap_src.flip(); + needData = false; + } else { + unwrap_src.clear(); + needData = true; + } + synchronized (unwrapLock) { + int x; + do { + if (needData) { + do { + x = chan.read (unwrap_src); + } while (x == 0); + if (x == -1) { + throw new IOException ("connection closed for reading"); + } + unwrap_src.flip(); + } + r.result = engine.unwrap (unwrap_src, r.buf); + status = r.result.getStatus(); + if (status == Status.BUFFER_UNDERFLOW) { + if (unwrap_src.limit() == unwrap_src.capacity()) { + /* buffer not big enough */ + unwrap_src = realloc ( + unwrap_src, false, BufType.PACKET + ); + } else { + /* Buffer not full, just need to read more + * data off the channel. Reset pointers + * for reading off SocketChannel + */ + unwrap_src.position (unwrap_src.limit()); + unwrap_src.limit (unwrap_src.capacity()); + } + needData = true; + } else if (status == Status.BUFFER_OVERFLOW) { + r.buf = realloc (r.buf, true, BufType.APPLICATION); + needData = false; + } else if (status == Status.CLOSED) { + closed = true; + r.buf.flip(); + return r; + } + } while (status != Status.OK); + } + u_remaining = unwrap_src.remaining(); + return r; + } + } + + WrapperResult sendData (ByteBuffer src) throws IOException { + ByteBuffer[] buffers = new ByteBuffer[1]; + buffers[0] = src; + return sendData(buffers, 0, 1); + } + + /** + * send the data in the given ByteBuffer. If a handshake is needed + * then this is handled within this method. When this call returns, + * all of the given user data has been sent and any handshake has been + * completed. Caller should check if engine has been closed. + */ + WrapperResult sendData (ByteBuffer[] src, int offset, int len) throws IOException { + WrapperResult r = WrapperResult.createOK(); + while (countBytes(src, offset, len) > 0) { + r = wrapper.wrapAndSend(src, offset, len, false); + Status status = r.result.getStatus(); + if (status == Status.CLOSED) { + doClosure (); + return r; + } + HandshakeStatus hs_status = r.result.getHandshakeStatus(); + if (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + doHandshake(hs_status); + } + } + return r; + } + + /** + * read data thru the engine into the given ByteBuffer. If the + * given buffer was not large enough, a new one is allocated + * and returned. This call handles handshaking automatically. + * Caller should check if engine has been closed. + */ + WrapperResult recvData (ByteBuffer dst) throws IOException { + /* we wait until some user data arrives */ + int mark = dst.position(); + WrapperResult r = null; + assert dst.position() == 0; + while (dst.position() == 0) { + r = wrapper.recvAndUnwrap (dst); + dst = (r.buf != dst) ? r.buf: dst; + Status status = r.result.getStatus(); + if (status == Status.CLOSED) { + doClosure (); + return r; + } + + HandshakeStatus hs_status = r.result.getHandshakeStatus(); + if (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + doHandshake (hs_status); + } + } + Utils.flipToMark(dst, mark); + return r; + } + + /* we've received a close notify. Need to call wrap to send + * the response + */ + void doClosure () throws IOException { + try { + handshaking.lock(); + ByteBuffer tmp = allocate(BufType.APPLICATION); + WrapperResult r; + do { + tmp.clear(); + tmp.flip (); + r = wrapper.wrapAndSend(tmp, true); + } while (r.result.getStatus() != Status.CLOSED); + } finally { + handshaking.unlock(); + } + } + + /* do the (complete) handshake after acquiring the handshake lock. + * If two threads call this at the same time, then we depend + * on the wrapper methods being idempotent. eg. if wrapAndSend() + * is called with no data to send then there must be no problem + */ + @SuppressWarnings("fallthrough") + void doHandshake (HandshakeStatus hs_status) throws IOException { + boolean wasBlocking = false; + try { + wasBlocking = chan.isBlocking(); + handshaking.lock(); + chan.configureBlocking(true); + ByteBuffer tmp = allocate(BufType.APPLICATION); + while (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + WrapperResult r = null; + switch (hs_status) { + case NEED_TASK: + Runnable task; + while ((task = engine.getDelegatedTask()) != null) { + /* run in current thread, because we are already + * running an external Executor + */ + task.run(); + } + /* fall thru - call wrap again */ + case NEED_WRAP: + tmp.clear(); + tmp.flip(); + r = wrapper.wrapAndSend(tmp, false); + break; + + case NEED_UNWRAP: + tmp.clear(); + r = wrapper.recvAndUnwrap (tmp); + if (r.buf != tmp) { + tmp = r.buf; + } + assert tmp.position() == 0; + break; + } + hs_status = r.result.getHandshakeStatus(); + } + Log.logSSL(getSessionInfo()); + if (!wasBlocking) { + chan.configureBlocking(false); + } + } finally { + handshaking.unlock(); + } + } + + String getSessionInfo() { + StringBuilder sb = new StringBuilder(); + String application = engine.getApplicationProtocol(); + SSLSession sess = engine.getSession(); + String cipher = sess.getCipherSuite(); + String protocol = sess.getProtocol(); + sb.append("Handshake complete alpn: ") + .append(application) + .append(", Cipher: ") + .append(cipher) + .append(", Protocol: ") + .append(protocol); + return sb.toString(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java new file mode 100644 index 00000000000..8ec5786a687 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.security.AccessControlContext; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import java.net.http.SSLDelegate.BufType; +import java.net.http.SSLDelegate.WrapperResult; + +/** + * An SSL tunnel built on a Plain (CONNECT) TCP tunnel. + */ +class SSLTunnelConnection extends HttpConnection { + + final PlainTunnelingConnection delegate; + protected SSLDelegate sslDelegate; + private volatile boolean connected; + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + this.sslDelegate = new SSLDelegate(delegate.channel(), client, null); + connected = true; + } + + @Override + boolean connected() { + return connected && delegate.connected(); + } + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenAccept((Void v) -> { + try { + // can this block? + this.sslDelegate = new SSLDelegate(delegate.channel(), + client, + null); + connected = true; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + SSLTunnelConnection(InetSocketAddress addr, + HttpClientImpl client, + InetSocketAddress proxy, + AccessControlContext acc) { + super(addr, client); + delegate = new PlainTunnelingConnection(addr, proxy, client, acc); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "SSLTunnelConnection: " + super.toString(); + } + + private static long countBytes(ByteBuffer[] buffers, int start, int number) { + long c = 0; + for (int i=0; i 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long l = buffer.remaining(); + WrapperResult r = sslDelegate.sendData(buffer); + if (r.result.getStatus() == Status.CLOSED) { + if (l > 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + void close() { + try { + //System.err.println ("Closing: " + this); + delegate.channel().close(); // TODO: proper close + } catch (IOException ex) { + } + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length); + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.result.bytesProduced(); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return true; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java new file mode 100644 index 00000000000..271e81c7a68 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.function.LongConsumer; + +/** + * Http/2 Stream + */ +class Stream extends ExchangeImpl { + + void debugPrint() { + } + + @Override + @SuppressWarnings("unchecked") + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return null; + } + + Stream(HttpClientImpl client, Http2Connection connection, Exchange e) { + super(e); + } + + @Override + HttpResponseImpl getResponse() throws IOException { + return null; + } + + @Override + void sendRequest() throws IOException, InterruptedException { + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + } + + @Override + void sendBody() throws IOException, InterruptedException { + } + + @Override + CompletableFuture sendHeadersAsync() { + return null; + } + + @Override + CompletableFuture getResponseAsync(Void v) { + return null; + } + + @Override + CompletableFuture sendBodyAsync() { + return null; + } + + @Override + void cancel() { + } + + + @Override + CompletableFuture sendRequestAsync() { + return null; + } + + @Override + T responseBody(HttpResponse.BodyProcessor processor) throws IOException { + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java new file mode 100644 index 00000000000..87786a62a77 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +/** + * Timeout event delivered by selector thread. Executes given handler + * if the timer not cancelled first. + * + * Register with HttpClientImpl.registerTimer(TimeoutEvent) + * + * Cancel with HttpClientImpl.cancelTimer(TimeoutEvent) + */ +abstract class TimeoutEvent { + + final long timeval; + + long delta; // used when on queue + + TimeoutEvent(long timeval) { this.timeval = timeval; } + + public abstract void handle(); + + /** Returns the timevalue in milli-seconds */ + public long timevalMillis() { return timeval; } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java new file mode 100644 index 00000000000..a201a23f4bd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +package java.net.http; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.net.NetPermission; +import java.net.URI; +import java.net.URLPermission; +import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.net.ssl.SSLParameters; +import sun.net.NetProperties; + +/** + * Miscellaneous utilities + */ +class Utils { + + /** + * Allocated buffer size. Must never be higher than 16K. But can be lower + * if smaller allocation units preferred. HTTP/2 mandates that all + * implementations support frame payloads of at least 16K. + */ + public static final int BUFSIZE = 16 * 1024; + + /** Validates a RFC7230 token */ + static void validateToken(String token, String errormsg) { + int length = token.length(); + for (int i = 0; i < length; i++) { + int c = token.codePointAt(i); + if (c >= 0x30 && c <= 0x39 // 0 - 9 + || (c >= 0x61 && c <= 0x7a) // a - z + || (c >= 0x41 && c <= 0x5a) // A - Z + || (c >= 0x21 && c <= 0x2e && c != 0x22 && c != 0x27 && c != 0x2c) + || (c >= 0x5e && c <= 0x60) + || (c == 0x7c) || (c == 0x7e)) { + } else { + throw new IllegalArgumentException(errormsg); + } + } + } + + /** + * Return sthe security permission required for the given details. + * If method is CONNECT, then uri must be of form "scheme://host:port" + */ + static URLPermission getPermission(URI uri, + String method, + Map> headers) { + StringBuilder sb = new StringBuilder(); + + String urlstring, actionstring; + + if (method.equals("CONNECT")) { + urlstring = uri.toString(); + actionstring = "CONNECT"; + } else { + sb.append(uri.getScheme()) + .append("://") + .append(uri.getHost()) + .append(uri.getPath()); + urlstring = sb.toString(); + + sb = new StringBuilder(); + sb.append(method); + if (headers != null && !headers.isEmpty()) { + sb.append(':'); + Set keys = headers.keySet(); + boolean first = true; + for (String key : keys) { + if (!first) { + sb.append(','); + } + sb.append(key); + first = false; + } + } + actionstring = sb.toString(); + } + return new URLPermission(urlstring, actionstring); + } + + static void checkNetPermission(String target) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) + return; + NetPermission np = new NetPermission(target); + sm.checkPermission(np); + } + + static int getIntegerNetProperty(String name, int defaultValue) { + return AccessController.doPrivileged((PrivilegedAction)() -> + NetProperties.getInteger(name, defaultValue) ); + } + + static String getNetProperty(String name) { + return AccessController.doPrivileged((PrivilegedAction)() -> + NetProperties.get(name) ); + } + + static SSLParameters copySSLParameters(SSLParameters p) { + SSLParameters p1 = new SSLParameters(); + p1.setAlgorithmConstraints(p.getAlgorithmConstraints()); + p1.setCipherSuites(p.getCipherSuites()); + p1.setEnableRetransmissions(p.getEnableRetransmissions()); + p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm()); + p1.setMaximumPacketSize(p.getMaximumPacketSize()); + p1.setNeedClientAuth(p.getNeedClientAuth()); + p1.setProtocols(p.getProtocols().clone()); + p1.setSNIMatchers(p.getSNIMatchers()); + p1.setServerNames(p.getServerNames()); + p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder()); + p1.setWantClientAuth(p.getWantClientAuth()); + return p1; + } + + + /** Resumes reading into the given buffer. */ + static void unflip(ByteBuffer buf) { + buf.position(buf.limit()); + buf.limit(buf.capacity()); + } + + /** + * Set limit to position, and position to mark. + * + * + * @param buffer + * @param mark + */ + static void flipToMark(ByteBuffer buffer, int mark) { + buffer.limit(buffer.position()); + buffer.position(mark); + } + + /** Compact and leave ready for reading. */ + static void compact(List buffers) { + for (ByteBuffer b : buffers) { + b.compact(); + b.flip(); + } + } + + static String stackTrace(Throwable t) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + String s = null; + try { + PrintStream p = new PrintStream(bos, true, "US-ASCII"); + t.printStackTrace(p); + s = bos.toString("US-ASCII"); + } catch (UnsupportedEncodingException ex) { + // can't happen + } + return s; + } + + /** Copies as much of src to dst as possible. */ + static void copy (ByteBuffer src, ByteBuffer dst) { + int srcLen = src.remaining(); + int dstLen = dst.remaining(); + if (srcLen > dstLen) { + int diff = srcLen - dstLen; + int limit = src.limit(); + src.limit(limit - diff); + dst.put(src); + src.limit(limit); + } else { + dst.put(src); + } + } + + static ByteBuffer copy(ByteBuffer src) { + ByteBuffer dst = ByteBuffer.allocate(src.remaining()); + dst.put(src); + dst.flip(); + return dst; + } + + static String combine(String[] s) { + StringBuilder sb = new StringBuilder(); + sb.append('['); + boolean first = true; + for (String s1 : s) { + if (!first) { + sb.append(", "); + first = false; + } + sb.append(s1); + } + sb.append(']'); + return sb.toString(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java new file mode 100644 index 00000000000..fd6d4ae2497 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + *

    High level HTTP API

    + * This provides a high-level client interface to HTTP (versions 1.1 and 2). + * Synchronous and asynchronous (via + * {@link java.util.concurrent.CompletableFuture}) modes are provided. The main + * classes defined are: + *
      + *
    • {@link java.net.http.HttpClient}
    • + *
    • {@link java.net.http.HttpRequest}
    • + *
    • {@link java.net.http.HttpResponse}
    • + *
    + * + * @since 9 + */ +package java.net.http; diff --git a/jdk/test/com/sun/net/httpserver/FileServerHandler.java b/jdk/test/com/sun/net/httpserver/FileServerHandler.java index c27fe96e406..00ccd7d1a43 100644 --- a/jdk/test/com/sun/net/httpserver/FileServerHandler.java +++ b/jdk/test/com/sun/net/httpserver/FileServerHandler.java @@ -23,6 +23,7 @@ import java.util.*; import java.util.concurrent.*; +import java.util.logging.*; import java.io.*; import java.net.*; import java.security.*; @@ -36,6 +37,10 @@ import com.sun.net.httpserver.*; * Must be given an abs pathname to the document root. * Directory listings together with text + html files * can be served. + * + * File Server created on files sub-path + * + * Echo server created on echo sub-path */ public class FileServerHandler implements HttpHandler { @@ -44,14 +49,24 @@ public class FileServerHandler implements HttpHandler { System.out.println ("usage: java FileServerHandler rootDir port logfilename"); System.exit(1); } + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + String rootDir = args[0]; int port = Integer.parseInt (args[1]); String logfile = args[2]; - HttpServer server = HttpServer.create (new InetSocketAddress (8000), 0); + HttpServer server = HttpServer.create (new InetSocketAddress (port), 0); HttpHandler h = new FileServerHandler (rootDir); + HttpHandler h1 = new EchoHandler (); - HttpContext c = server.createContext ("/", h); + HttpContext c = server.createContext ("/files", h); c.getFilters().add (new LogFilter (new File (logfile))); + HttpContext c1 = server.createContext ("/echo", h1); + c.getFilters().add (new LogFilter (new File (logfile))); + c1.getFilters().add (new LogFilter (new File (logfile))); server.setExecutor (Executors.newCachedThreadPool()); server.start (); } @@ -72,7 +87,8 @@ public class FileServerHandler implements HttpHandler { URI uri = t.getRequestURI(); String path = uri.getPath(); - while (is.read () != -1) ; + int x = 0; + while (is.read () != -1) x++; is.close(); File f = new File (docroot, path); if (!f.exists()) { @@ -164,3 +180,61 @@ public class FileServerHandler implements HttpHandler { t.close(); } } + +class EchoHandler implements HttpHandler { + + byte[] read(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + byte[] result = new byte[0]; + + while (true) { + int n = is.read(buf); + if (n > 0) { + byte[] b1 = new byte[result.length + n]; + System.arraycopy(result, 0, b1, 0, result.length); + System.arraycopy(buf, 0, b1, result.length, n); + result = b1; + } else if (n == -1) { + return result; + } + } + } + + public void handle (HttpExchange t) + throws IOException + { + InputStream is = t.getRequestBody(); + Headers map = t.getRequestHeaders(); + String fixedrequest = map.getFirst ("XFixed"); + + // return the number of bytes received (no echo) + String summary = map.getFirst ("XSummary"); + if (fixedrequest != null && summary == null) { + byte[] in = read(is); + t.sendResponseHeaders(200, in.length); + OutputStream os = t.getResponseBody(); + os.write(in); + os.close(); + is.close(); + } else { + OutputStream os = t.getResponseBody(); + byte[] buf = new byte[64 * 1024]; + t.sendResponseHeaders(200, 0); + int n, count=0;; + + while ((n = is.read(buf)) != -1) { + if (summary == null) { + os.write(buf, 0, n); + } + count += n; + } + if (summary != null) { + String s = Integer.toString(count); + os.write(s.getBytes()); + } + os.close(); + is.close(); + } + } +} + diff --git a/jdk/test/java/net/httpclient/APIErrors.java b/jdk/test/java/net/httpclient/APIErrors.java new file mode 100644 index 00000000000..845c665088a --- /dev/null +++ b/jdk/test/java/net/httpclient/APIErrors.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm APIErrors + */ +//package javaapplication16; + +import com.sun.net.httpserver.*; +import java.io.IOException; +import java.net.*; +import java.net.http.*; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.*; +import java.util.function.Supplier; + +/** + * Does stupid things with API, to check appropriate errors/exceptions thrown + */ +public class APIErrors { + + static HttpServer s1 = null; + static ExecutorService executor = null; + static int port; + static HttpClient client; + static String httproot, fileuri, fileroot; + static List clients = new LinkedList<>(); + + public static void main(String[] args) throws Exception { + initServer(); + fileroot = System.getProperty("test.src") + "/docs"; + + client = HttpClient.create().build(); + + clients.add(HttpClient.getDefault()); + + try { + test1(); + test2(); + test3(); + } finally { + s1.stop(0); + executor.shutdownNow(); + for (HttpClient client : clients) + client.executorService().shutdownNow(); + } + } + + static void reject(Runnable r, Class extype) { + try { + r.run(); + throw new RuntimeException("Expected: " + extype); + } catch (Throwable t) { + if (!extype.isAssignableFrom(t.getClass())) { + throw new RuntimeException("Wrong exception type: " + extype + " / " + +t.getClass()); + } + } + } + + static void accept(Runnable r) { + try { + r.run(); + } catch (Throwable t) { + throw new RuntimeException("Unexpected exception: " + t); + } + } + + static void checkNonNull(Supplier r) { + if (r.get() == null) + throw new RuntimeException("Unexpected null return:"); + } + + static void assertTrue(Supplier r) { + if (r.get() == false) + throw new RuntimeException("Assertion failure:"); + } + + // HttpClient.Builder + static void test1() throws Exception { + System.out.println("Test 1"); + HttpClient.Builder cb = HttpClient.create(); + InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); + reject(() -> { cb.priority(-1);}, IllegalArgumentException.class); + reject(() -> { cb.priority(500);}, IllegalArgumentException.class); + accept(() -> { cb.priority(1);}); + accept(() -> { cb.priority(255);}); + + accept(() -> {clients.add(cb.build()); clients.add(cb.build());}); + } + + static void test2() throws Exception { + System.out.println("Test 2"); + HttpClient.Builder cb = HttpClient.create(); + InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); + cb.proxy(ProxySelector.of(addr)); + HttpClient c = cb.build(); + clients.add(c); + checkNonNull(()-> {return c.executorService();}); + assertTrue(()-> {return c.followRedirects() == HttpClient.Redirect.NEVER;}); + assertTrue(()-> {return !c.authenticator().isPresent();}); + } + + static URI accessibleURI() { + return URI.create(fileuri); + } + + static HttpRequest request() { + return HttpRequest.create(accessibleURI()) + .GET(); + } + + static void test3() throws Exception { + System.out.println("Test 3"); + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp = r1.response(); + HttpResponse resp1 = r1.response(); + } catch (IOException |InterruptedException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp = r1.response(); + HttpResponse resp1 = r1.responseAsync().get(); + } catch (IOException |InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp1 = r1.responseAsync().get(); + HttpResponse resp = r1.response(); + } catch (IOException |InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + } + + static class Auth extends java.net.Authenticator { + int count = 0; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (count++ == 0) { + return new PasswordAuthentication("user", "passwd".toCharArray()); + } else { + return new PasswordAuthentication("user", "goober".toCharArray()); + } + } + int count() { + return count; + } + } + + public static void initServer() throws Exception { + String root = System.getProperty ("test.src")+ "/docs"; + InetSocketAddress addr = new InetSocketAddress (0); + s1 = HttpServer.create (addr, 0); + if (s1 instanceof HttpsServer) { + throw new RuntimeException ("should not be httpsserver"); + } + HttpHandler h = new FileServerHandler(root); + + HttpContext c1 = s1.createContext("/files", h); + + executor = Executors.newCachedThreadPool(); + s1.setExecutor (executor); + s1.start(); + + port = s1.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httproot = "http://127.0.0.1:" + port + "/files/"; + fileuri = httproot + "foo.txt"; + } +} diff --git a/jdk/test/java/net/httpclient/BasicAuthTest.java b/jdk/test/java/net/httpclient/BasicAuthTest.java new file mode 100644 index 00000000000..5e3fa6d3374 --- /dev/null +++ b/jdk/test/java/net/httpclient/BasicAuthTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +/** + * @test + * @bug 8087112 + * @run main/othervm BasicAuthTest + * @summary Basic Authentication Test + */ + +import com.sun.net.httpserver.BasicAuthenticator; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class BasicAuthTest { + + static volatile boolean ok; + static final String RESPONSE = "Hello world"; + static final String POST_BODY = "This is the POST body 123909090909090"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + ClientAuth ca = new ClientAuth(); + ServerAuth sa = new ServerAuth("foo realm"); + serverContext.setAuthenticator(sa); + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .authenticator(ca) + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri).GET(); + + HttpResponse resp = req.response(); + ok = resp.statusCode() == 200 && + resp.body(HttpResponse.asString()).equals(RESPONSE); + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + + // repeat same request, should succeed but no additional authenticator calls + + req = client.request(uri).GET(); + resp = req.response(); + ok = resp.statusCode() == 200 && + resp.body(HttpResponse.asString()).equals(RESPONSE); + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + + // try a POST + + req = client.request(uri) + .body(HttpRequest.fromString(POST_BODY)) + .POST(); + resp = req.response(); + ok = resp.statusCode() == 200; + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class ServerAuth extends BasicAuthenticator { + + ServerAuth(String realm) { + super(realm); + } + + @Override + public boolean checkCredentials(String username, String password) { + if (!"user".equals(username) || !"passwd".equals(password)) { + return false; + } + return true; + } + + } + + static class ClientAuth extends java.net.Authenticator { + volatile int count = 0; + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + count++; + return new PasswordAuthentication("user", "passwd".toCharArray()); + } + } + + static class Handler implements HttpHandler { + static volatile boolean ok; + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + if (method.equalsIgnoreCase("POST")) { + String requestBody = new String(is.readAllBytes(), US_ASCII); + if (!requestBody.equals(POST_BODY)) { + he.sendResponseHeaders(500, -1); + ok = false; + } else { + he.sendResponseHeaders(200, -1); + ok = true; + } + } else { // GET + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + ok = true; + } + } + + } +} diff --git a/jdk/test/java/net/httpclient/HeadersTest.java b/jdk/test/java/net/httpclient/HeadersTest.java new file mode 100644 index 00000000000..61faeaa1ec9 --- /dev/null +++ b/jdk/test/java/net/httpclient/HeadersTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.http.HttpRequest; +import java.net.URI; + +/** + * @test + * @bug 8087112 + * @summary Basic test for headers + */ +public class HeadersTest { + + static final URI TEST_URI = URI.create("http://www.foo.com/"); + + static void bad(String name) { + HttpRequest.Builder builder = HttpRequest.create(TEST_URI); + try { + builder.header(name, "foo"); + throw new RuntimeException("Expected IAE for header:" + name); + } catch (IllegalArgumentException expected) { } + } + + static void good(String name) { + HttpRequest.Builder builder = HttpRequest.create(TEST_URI); + try { + builder.header(name, "foo"); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Unexpected IAE for header:" + name); + } + } + + public static void main(String[] args) { + bad("bad:header"); + bad("Foo\n"); + good("X-Foo!"); + good("Bar~"); + good("x"); + bad(" "); + bad("Bar\r\n"); + good("Hello#world"); + good("Qwer#ert"); + } +} diff --git a/jdk/test/java/net/httpclient/HttpUtils.java b/jdk/test/java/net/httpclient/HttpUtils.java new file mode 100644 index 00000000000..206cdab362e --- /dev/null +++ b/jdk/test/java/net/httpclient/HttpUtils.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import static java.net.http.HttpRequest.fromByteArray; +import static java.net.http.HttpRequest.fromByteArrays; +import static java.net.http.HttpRequest.fromFile; +import static java.net.http.HttpRequest.fromInputStream; +import static java.net.http.HttpRequest.fromString; +import java.net.http.HttpResponse; +import static java.net.http.HttpResponse.asByteArray; +import static java.net.http.HttpResponse.asFile; +import static java.net.http.HttpResponse.asInputStream; +import static java.net.http.HttpResponse.asString; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +public final class HttpUtils { + + static final int DEFAULT_OFFSET = 10; + static final int DEFAULT_LENGTH = 1000; + static final String midSizedFilename = "/files/notsobigfile.txt"; + static final String smallFilename = "/files/smallfile.txt"; + static final Path midSizedFile; + static final Path smallFile; + static final String fileroot; + + public enum RequestBody { + STRING, FILE, BYTE_ARRAY, BYTE_ARRAY_OFFSET, INPUTSTREAM, STRING_WITH_CHARSET, + } + + static { + fileroot = System.getProperty("test.src") + "/docs"; + midSizedFile = Paths.get(fileroot + midSizedFilename); + smallFile = Paths.get(fileroot + smallFilename); + } + + static public String getFileContent(String path) throws IOException { + FileInputStream fis = new FileInputStream(path); + byte[] buf = new byte[2 * 1024]; + StringBuilder sb = new StringBuilder(); + int byteRead; + while ((byteRead = fis.read(buf)) != -1) { + sb.append(new String(buf, 0, byteRead, "US-ASCII")); + } + return sb.toString(); + } + + public static HttpRequest.Builder getHttpRequestBuilder(final HttpClient client, + final String requestType, + final URI uri) + throws IOException + { + HttpRequest.Builder builder; + String filename = smallFile.toFile().getAbsolutePath(); + String fileContents = HttpUtils.getFileContent(filename); + byte buf[] = fileContents.getBytes(); + switch (requestType) { + case "InputStream": + InputStream inputStream = new FileInputStream(smallFile.toFile()); + builder = client.request(uri) + .body(fromInputStream(inputStream)); + break; + case "byteArray": + builder = client.request(uri) + .body(fromByteArray(buf)); + break; + case "byteArrays": + Iterable iterable = Arrays.asList(buf); + builder = client.request(uri) + .body(fromByteArrays(iterable.iterator())); + break; + case "string": + builder = client.request(uri) + .body(fromString(fileContents)); + break; + case "byteArray_offset": + builder = client.request(uri) + .body(fromByteArray(buf, + DEFAULT_OFFSET, + DEFAULT_LENGTH)); + break; + case "file": + builder = client.request(uri) + .body(fromFile(smallFile)); + break; + case "string_charset": + builder = client.request(uri) + .body(fromString(new String(buf), + Charset.defaultCharset())); + break; + default: + builder = null; + break; + } + return builder; + } + + public static void checkResponse(final HttpResponse response, + String requestType, + final String responseType) + throws IOException + { + String filename = smallFile.toFile().getAbsolutePath(); + String fileContents = HttpUtils.getFileContent(filename); + if (requestType.equals("byteArray_offset")) { + fileContents = fileContents.substring(DEFAULT_OFFSET, + DEFAULT_OFFSET + DEFAULT_LENGTH); + } + byte buf[] = fileContents.getBytes(); + String responseBody; + switch (responseType) { + case "string": + responseBody = response.body(asString()); + if (!responseBody.equals(fileContents)) { + throw new RuntimeException(); + } + break; + case "byteArray": + byte arr[] = response.body(asByteArray()); + if (!Arrays.equals(arr, buf)) { + throw new RuntimeException(); + } + break; + case "file": + response.body(asFile(Paths.get("barf.txt"))); + Path downloaded = Paths.get("barf.txt"); + if (Files.size(downloaded) != fileContents.length()) { + throw new RuntimeException("Size mismatch"); + } + break; + case "InputStream": + InputStream is = response.body(asInputStream()); + byte arr1[] = new byte[1024]; + int byteRead; + StringBuilder sb = new StringBuilder(); + while ((byteRead = is.read(arr1)) != -1) { + sb.append(new String(arr1, 0, byteRead)); + } + if (!sb.toString().equals(fileContents)) { + throw new RuntimeException(); + } + break; + } + } +} diff --git a/jdk/test/java/net/httpclient/ImmutableHeaders.java b/jdk/test/java/net/httpclient/ImmutableHeaders.java new file mode 100644 index 00000000000..9fd6a2162cc --- /dev/null +++ b/jdk/test/java/net/httpclient/ImmutableHeaders.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + */ + +/** + * @test + * @bug 8087112 + * @run main/othervm ImmutableHeaders + * @summary ImmutableHeaders + */ + +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.Headers; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.List; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class ImmutableHeaders { + + final static String RESPONSE = "Hello world"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri) + .headers("X-Foo", "bar") + .headers("X-Bar", "foo") + .GET(); + + try { + HttpHeaders hd = req.headers(); + List v = hd.allValues("X-Foo"); + if (!v.get(0).equals("bar")) + throw new RuntimeException("Test failed"); + v.add("XX"); + throw new RuntimeException("Test failed"); + } catch (UnsupportedOperationException ex) { + } + HttpResponse resp = req.response(); + try { + HttpHeaders hd = resp.headers(); + List v = hd.allValues("X-Foo-Response"); + if (!v.get(0).equals("resp")) + throw new RuntimeException("Test failed"); + v.add("XX"); + throw new RuntimeException("Test failed"); + } catch (UnsupportedOperationException ex) { + } + + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class Handler implements HttpHandler { + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + Headers h = he.getResponseHeaders(); + h.add("X-Foo-Response", "resp"); + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + } + + } +} diff --git a/jdk/test/java/net/httpclient/LightWeightHttpServer.java b/jdk/test/java/net/httpclient/LightWeightHttpServer.java new file mode 100644 index 00000000000..315849521a0 --- /dev/null +++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + */ +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.net.ssl.SSLContext; +import jdk.testlibrary.SimpleSSLContext; + +public class LightWeightHttpServer { + + static SSLContext ctx; + static HttpServer httpServer; + static HttpsServer httpsServer; + static ExecutorService executor; + static int port; + static int httpsport; + static String httproot; + static String httpsroot; + static ProxyServer proxy; + static int proxyPort; + static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; + static RedirectHandler redirectHandler, redirectHandlerSecure; + static DelayHandler delayHandler; + static final String midSizedFilename = "/files/notsobigfile.txt"; + static final String smallFilename = "/files/smallfile.txt"; + static Path midSizedFile; + static Path smallFile; + static String fileroot; + + public static void initServer() throws IOException { + + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + + String root = System.getProperty("test.src") + "/docs"; + InetSocketAddress addr = new InetSocketAddress(0); + httpServer = HttpServer.create(addr, 0); + if (httpServer instanceof HttpsServer) { + throw new RuntimeException("should not be httpsserver"); + } + httpsServer = HttpsServer.create(addr, 0); + HttpHandler h = new FileServerHandler(root); + + HttpContext c1 = httpServer.createContext("/files", h); + HttpContext c2 = httpsServer.createContext("/files", h); + HttpContext c3 = httpServer.createContext("/echo", new EchoHandler()); + redirectHandler = new RedirectHandler("/redirect"); + redirectHandlerSecure = new RedirectHandler("/redirect"); + HttpContext c4 = httpServer.createContext("/redirect", redirectHandler); + HttpContext c41 = httpsServer.createContext("/redirect", redirectHandlerSecure); + HttpContext c5 = httpsServer.createContext("/echo", new EchoHandler()); + HttpContext c6 = httpServer.createContext("/keepalive", new KeepAliveHandler()); + redirectErrorHandler = new RedirectErrorHandler("/redirecterror"); + redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror"); + HttpContext c7 = httpServer.createContext("/redirecterror", redirectErrorHandler); + HttpContext c71 = httpsServer.createContext("/redirecterror", redirectErrorHandlerSecure); + delayHandler = new DelayHandler(); + HttpContext c8 = httpServer.createContext("/delay", delayHandler); + HttpContext c81 = httpsServer.createContext("/delay", delayHandler); + + executor = Executors.newCachedThreadPool(); + httpServer.setExecutor(executor); + httpsServer.setExecutor(executor); + ctx = new SimpleSSLContext().get(); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(ctx)); + httpServer.start(); + httpsServer.start(); + + port = httpServer.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httpsport = httpsServer.getAddress().getPort(); + System.out.println("HTTPS server port = " + httpsport); + httproot = "http://127.0.0.1:" + port + "/"; + httpsroot = "https://127.0.0.1:" + httpsport + "/"; + + proxy = new ProxyServer(0, false); + proxyPort = proxy.getPort(); + System.out.println("Proxy port = " + proxyPort); + } + + public static void stop() throws IOException { + if (httpServer != null) { + httpServer.stop(0); + } + if (httpsServer != null) { + httpsServer.stop(0); + } + if (proxy != null) { + proxy.close(); + } + if (executor != null) { + executor.shutdownNow(); + } + } + + static class RedirectErrorHandler implements HttpHandler { + + String root; + volatile int count = 1; + + RedirectErrorHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + String redirect = root + "/foo/" + Integer.toString(count); + increment(); + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } + } + + static class RedirectHandler implements HttpHandler { + + String root; + volatile int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + + if (count++ < 1) { + map.add("Location", root + "/foo/" + count); + } else { + map.add("Location", SmokeTest.midSizedFilename); + } + t.sendResponseHeaders(301, -1); + t.close(); + } + + int count() { + return count; + } + + void reset() { + count = 0; + } + } + + static class KeepAliveHandler implements HttpHandler { + + volatile int counter = 0; + HashSet portSet = new HashSet<>(); + volatile int[] ports = new int[4]; + + void sleep(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) { + } + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + int remotePort = t.getRemoteAddress().getPort(); + String result = "OK"; + + int n = counter++; + /// First test + if (n < 4) { + ports[n] = remotePort; + } + if (n == 3) { + // check all values in ports[] are the same + if (ports[0] != ports[1] || ports[2] != ports[3] + || ports[0] != ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + // Second test + if (n >= 4 && n < 8) { + // delay to ensure ports are different + sleep(500); + ports[n - 4] = remotePort; + } + if (n == 7) { + // should be all different + if (ports[0] == ports[1] || ports[2] == ports[3] + || ports[0] == ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + System.out.printf("Ports: %d, %d, %d, %d\n", + ports[0], ports[1], ports[2], ports[3]); + } + // setup for third test + for (int i = 0; i < 4; i++) { + portSet.add(ports[i]); + } + } + // Third test + if (n > 7) { + // just check that port is one of the ones in portSet + if (!portSet.contains(remotePort)) { + System.out.println("UNEXPECTED REMOTE PORT " + remotePort); + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + byte[] buf = new byte[2048]; + + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + t.sendResponseHeaders(200, result.length()); + OutputStream o = t.getResponseBody(); + o.write(result.getBytes("US-ASCII")); + t.close(); + } + } + + static class DelayHandler implements HttpHandler { + + CyclicBarrier bar1 = new CyclicBarrier(2); + CyclicBarrier bar2 = new CyclicBarrier(2); + CyclicBarrier bar3 = new CyclicBarrier(2); + + CyclicBarrier barrier1() { + return bar1; + } + + CyclicBarrier barrier2() { + return bar2; + } + + @Override + public synchronized void handle(HttpExchange he) throws IOException { + byte[] buf = Util.readAll(he.getRequestBody()); + try { + bar1.await(); + bar2.await(); + } catch (InterruptedException | BrokenBarrierException e) { + } + he.sendResponseHeaders(200, -1); // will probably fail + he.close(); + } + } +} diff --git a/jdk/test/java/net/httpclient/ManyRequests.java b/jdk/test/java/net/httpclient/ManyRequests.java new file mode 100644 index 00000000000..10081f5def7 --- /dev/null +++ b/jdk/test/java/net/httpclient/ManyRequests.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm ManyRequests + * @summary Send a large number of requests asynchronously + */ + +//package javaapplication16; + +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLContext; +import jdk.testlibrary.SimpleSSLContext; + +public class ManyRequests { + + public static void main(String[] args) throws Exception { + SSLContext ctx = new SimpleSSLContext().get(); + + InetSocketAddress addr = new InetSocketAddress(0); + HttpsServer server = HttpsServer.create(addr, 0); + server.setHttpsConfigurator(new HttpsConfigurator(ctx)); + + HttpClient client = HttpClient.create() + .sslContext(ctx) + .build(); + try { + test(server, client); + System.out.println("OK"); + } finally { + server.stop(0); + client.executorService().shutdownNow(); + } + } + + static final int REQUESTS = 1000; + + static void test(HttpsServer server, HttpClient client) throws Exception { + int port = server.getAddress().getPort(); + URI uri = new URI("https://127.0.0.1:" + port + "/foo/x"); + server.createContext("/foo", new EchoHandler()); + server.start(); + + RequestLimiter limiter = new RequestLimiter(40); + Random rand = new Random(); + CompletableFuture[] results = new CompletableFuture[REQUESTS]; + HashMap bodies = new HashMap<>(); + + for (int i=0; i r.responseAsync()) + .thenCompose((resp) -> { + limiter.requestComplete(); + if (resp.statusCode() != 200) { + resp.bodyAsync(HttpResponse.ignoreBody()); + String s = "Expected 200, got: " + resp.statusCode(); + return completedWithIOException(s); + } + return resp.bodyAsync(HttpResponse.asByteArray()) + .thenApply((b) -> new Pair<>(resp, b)); + }) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal"); + + }); + } + // wait for them all to complete and throw exception in case of error + CompletableFuture.allOf(results).join(); + } + + static CompletableFuture completedWithIOException(String message) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(new IOException(message)); + return cf; + } + + static final class Pair { + Pair(T t, U u) { + this.t = t; this.u = u; + } + T t; + U u; + } + + /** + * A simple limiter for controlling the number of requests to be run in + * parallel whenOkToSend() is called which returns a CF that allows + * each individual request to proceed, or block temporarily (blocking occurs + * on the waiters list here. As each request actually completes + * requestComplete() is called to notify this object, and allow some + * requests to continue. + */ + static class RequestLimiter { + + static final CompletableFuture COMPLETED_FUTURE = + CompletableFuture.completedFuture(null); + + final int maxnumber; + final LinkedList> waiters; + int number; + boolean blocked; + + RequestLimiter(int maximum) { + waiters = new LinkedList<>(); + maxnumber = maximum; + } + + synchronized void requestComplete() { + number--; + // don't unblock until number of requests has halved. + if ((blocked && number <= maxnumber / 2) || + (!blocked && waiters.size() > 0)) { + int toRelease = Math.min(maxnumber - number, waiters.size()); + for (int i=0; i f = waiters.remove(); + number ++; + f.complete(null); + } + blocked = number >= maxnumber; + } + } + + synchronized CompletableFuture whenOkToSend() { + if (blocked || number + 1 >= maxnumber) { + blocked = true; + CompletableFuture r = new CompletableFuture<>(); + waiters.add(r); + return r; + } else { + number++; + return COMPLETED_FUTURE; + } + } + } + + static void check(boolean cond, Object... msg) { + if (cond) + return; + StringBuilder sb = new StringBuilder(); + for (Object o : msg) + sb.append(o); + throw new RuntimeException(sb.toString()); + } +} diff --git a/jdk/test/java/net/httpclient/ProxyServer.java b/jdk/test/java/net/httpclient/ProxyServer.java new file mode 100644 index 00000000000..4da9b5e1c55 --- /dev/null +++ b/jdk/test/java/net/httpclient/ProxyServer.java @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.*; +import java.io.*; +import java.util.*; +import java.security.*; + +/** + * A minimal proxy server that supports CONNECT tunneling. It does not do + * any header transformations. In future this could be added. + * Two threads are created per client connection. So, it's not + * intended for large numbers of parallel connections. + */ +public class ProxyServer extends Thread implements Closeable { + + ServerSocket listener; + int port; + volatile boolean debug; + + /** + * Create proxy on port (zero means don't care). Call getPort() + * to get the assigned port. + */ + public ProxyServer(Integer port) throws IOException { + this(port, false); + } + + public ProxyServer(Integer port, Boolean debug) throws IOException { + this.debug = debug; + listener = new ServerSocket(port); + this.port = listener.getLocalPort(); + setName("ProxyListener"); + setDaemon(true); + connections = new LinkedList<>(); + start(); + } + + public ProxyServer(String s) { } + + /** + * Returns the port number this proxy is listening on + */ + public int getPort() { + return port; + } + + /** + * Shuts down the proxy, probably aborting any connections + * currently open + */ + public void close() throws IOException { + if (debug) System.out.println("Proxy: closing"); + done = true; + listener.close(); + for (Connection c : connections) { + if (c.running()) { + c.close(); + } + } + } + + List connections; + + volatile boolean done; + + public void run() { + if (System.getSecurityManager() == null) { + execute(); + } else { + // so calling domain does not need to have socket permission + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + execute(); + return null; + } + }); + } + } + + public void execute() { + try { + while(!done) { + Socket s = listener.accept(); + if (debug) + System.out.println("Client: " + s); + Connection c = new Connection(s); + connections.add(c); + } + } catch(Throwable e) { + if (debug && !done) { + System.out.println("Fatal error: Listener: " + e); + e.printStackTrace(); + } + } + } + + /** + * Transparently forward everything, once we know what the destination is + */ + class Connection { + + Socket clientSocket, serverSocket; + Thread out, in; + volatile InputStream clientIn, serverIn; + volatile OutputStream clientOut, serverOut; + + boolean forwarding = false; + + final static int CR = 13; + final static int LF = 10; + + Connection(Socket s) throws IOException { + this.clientSocket= s; + this.clientIn = new BufferedInputStream(s.getInputStream()); + this.clientOut = s.getOutputStream(); + init(); + } + + byte[] readHeaders(InputStream is) throws IOException { + byte[] outbuffer = new byte[8000]; + int crlfcount = 0; + int bytecount = 0; + int c; + while ((c=is.read()) != -1 && bytecount < outbuffer.length) { + outbuffer[bytecount++] = (byte)c; + if (debug) System.out.write(c); + // were looking for CRLFCRLF sequence + if (c == CR || c == LF) { + switch(crlfcount) { + case 0: + if (c == CR) crlfcount ++; + break; + case 1: + if (c == LF) crlfcount ++; + break; + case 2: + if (c == CR) crlfcount ++; + break; + case 3: + if (c == LF) crlfcount ++; + break; + } + } else { + crlfcount = 0; + } + if (crlfcount == 4) { + break; + } + } + byte[] ret = new byte[bytecount]; + System.arraycopy(outbuffer, 0, ret, 0, bytecount); + return ret; + } + + boolean running() { + return out.isAlive() || in.isAlive(); + } + + public void close() throws IOException { + if (debug) System.out.println("Closing connection (proxy)"); + if (serverSocket != null) serverSocket.close(); + if (clientSocket != null) clientSocket.close(); + } + + int findCRLF(byte[] b) { + for (int i=0; i=0) { + buf[i--] = (byte)cmdLine.charAt(x--); + } + i++; + + commonInit(dest, 80); + serverOut.write(buf, i, buf.length-i); + proxyCommon(); + + } catch (URISyntaxException e) { + throw new IOException(e); + } + } + + void commonInit(String dest, int defaultPort) throws IOException { + int port; + String[] hostport = dest.split(":"); + if (hostport.length == 1) { + port = defaultPort; + } else { + port = Integer.parseInt(hostport[1]); + } + if (debug) System.out.printf("Server: (%s/%d)\n", hostport[0], port); + serverSocket = new Socket(hostport[0], port); + serverOut = serverSocket.getOutputStream(); + + serverIn = new BufferedInputStream(serverSocket.getInputStream()); + } + + void proxyCommon() throws IOException { + out = new Thread(() -> { + try { + byte[] bb = new byte[8000]; + int n; + while ((n = clientIn.read(bb)) != -1) { + serverOut.write(bb, 0, n); + } + serverSocket.close(); + clientSocket.close(); + } catch (IOException e) { + if (debug) { + System.out.println (e); + } + } + }); + in = new Thread(() -> { + try { + byte[] bb = new byte[8000]; + int n; + while ((n = serverIn.read(bb)) != -1) { + clientOut.write(bb, 0, n); + } + serverSocket.close(); + clientSocket.close(); + } catch (IOException e) { + if (debug) { + System.out.println(e); + e.printStackTrace(); + } + } + }); + out.setName("Proxy-outbound"); + out.setDaemon(true); + in.setDaemon(true); + in.setName("Proxy-inbound"); + out.start(); + in.start(); + } + + void doTunnel(String dest) throws IOException { + commonInit(dest, 443); + clientOut.write("HTTP/1.1 200 OK\r\n\r\n".getBytes()); + proxyCommon(); + } + } + + public static void main(String[] args) throws Exception { + int port = Integer.parseInt(args[0]); + boolean debug = args.length > 1 && args[1].equals("-debug"); + System.out.println("Debugging : " + debug); + ProxyServer ps = new ProxyServer(port, debug); + System.out.println("Proxy server listening on port " + ps.getPort()); + while (true) { + Thread.sleep(5000); + } + } +} diff --git a/jdk/test/java/net/httpclient/QuickResponses.java b/jdk/test/java/net/httpclient/QuickResponses.java new file mode 100644 index 00000000000..5de1f687552 --- /dev/null +++ b/jdk/test/java/net/httpclient/QuickResponses.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +/** + * @test + * @bug 8087112 + * @build Server + * @run main/othervm -Djava.net.HttpClient.log=all QuickResponses + */ + +/** + * Tests the buffering of data on connections across multiple + * responses + */ +public class QuickResponses { + + static Server server; + + static String response(String body) { + return "HTTP/1.1 200 OK\r\nContent-length: " + Integer.toString(body.length()) + + "\r\n\r\n" + body; + } + + static final String responses[] = { + "Lorem ipsum", + "dolor sit amet", + "consectetur adipiscing elit, sed do eiusmod tempor", + "quis nostrud exercitation ullamco", + "laboris nisi", + "ut", + "aliquip ex ea commodo consequat." + + "Duis aute irure dolor in reprehenderit in voluptate velit esse" + + "cillum dolore eu fugiat nulla pariatur.", + "Excepteur sint occaecat cupidatat non proident." + }; + + static String entireResponse() { + String s = ""; + for (String r : responses) { + s += response(r); + } + return s; + } + + public static void main(String[] args) throws Exception { + server = new Server(0); + URI uri = new URI(server.getURL()); + + HttpRequest request = HttpRequest.create(uri) + .GET(); + + CompletableFuture cf1 = request.responseAsync(); + Server.Connection s1 = server.activity(); + s1.send(entireResponse()); + + + HttpResponse r = cf1.join(); + if (r.statusCode()!= 200 || !r.body(HttpResponse.asString()).equals(responses[0])) + throw new RuntimeException("Failed on first response"); + + //now get the same identical response, synchronously to ensure same connection + int remaining = responses.length - 1; + + for (int i=0; i sockets; + AtomicInteger counter = new AtomicInteger(0); + + // waits up to 20 seconds for something to happen + // dont use this unless certain activity coming. + public Connection activity() { + for (int i = 0; i < 80 * 100; i++) { + for (Connection c : sockets) { + if (c.poll()) { + return c; + } + } + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + } + return null; + } + + // clears all current connections on Server. + public void reset() { + for (Connection c : sockets) { + c.close(); + } + } + + /** + * Reads data into an ArrayBlockingQueue where each String + * is a line of input, that was terminated by CRLF (not included) + */ + class Connection extends Thread { + Connection(Socket s) throws IOException { + this.socket = s; + id = counter.incrementAndGet(); + is = s.getInputStream(); + os = s.getOutputStream(); + incoming = new ArrayBlockingQueue<>(100); + setName("Server-Connection"); + setDaemon(true); + start(); + } + final Socket socket; + final int id; + final InputStream is; + final OutputStream os; + final ArrayBlockingQueue incoming; + + final static String CRLF = "\r\n"; + + // sentinel indicating connection closed + final static String CLOSED = "C.L.O.S.E.D"; + volatile boolean closed = false; + + @Override + public void run() { + byte[] buf = new byte[256]; + String s = ""; + try { + while (true) { + int n = is.read(buf); + if (n == -1) { + cleanup(); + return; + } + String s0 = new String(buf, 0, n, StandardCharsets.ISO_8859_1); + s = s + s0; + int i; + while ((i=s.indexOf(CRLF)) != -1) { + String s1 = s.substring(0, i+2); + incoming.put(s1); + if (i+2 == s.length()) { + s = ""; + break; + } + s = s.substring(i+2); + } + } + } catch (IOException |InterruptedException e1) { + cleanup(); + } catch (Throwable t) { + System.out.println("X: " + t); + cleanup(); + } + } + + @Override + public String toString() { + return "Server.Connection: " + socket.toString(); + } + + public void sendHttpResponse(int code, String body, String... headers) + throws IOException + { + String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; + for (int i=0; i()); + setName("Test-Server"); + setDaemon(true); + start(); + } + + Server() throws IOException { + this(0); + } + + int port() { + return ss.getLocalPort(); + } + + public String getURL() { + return "http://127.0.0.1:" + port() + "/foo/"; + } + + public void close() { + try { + ss.close(); + } catch (IOException e) { + } + for (Connection c : sockets) { + c.close(); + } + } + + @Override + public void run() { + while (true) { + try { + Socket s = ss.accept(); + Connection c = new Connection(s); + sockets.add(c); + } catch (IOException e) { + } + } + } + +} diff --git a/jdk/test/java/net/httpclient/SmokeTest.java b/jdk/test/java/net/httpclient/SmokeTest.java new file mode 100644 index 00000000000..ec516623179 --- /dev/null +++ b/jdk/test/java/net/httpclient/SmokeTest.java @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm SmokeTest + */ + +//package javaapplication16; + +import com.sun.net.httpserver.*; +import java.net.*; +import java.net.http.*; +import java.io.*; +import java.util.concurrent.*; +import javax.net.ssl.*; +import java.nio.file.*; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import jdk.testlibrary.SimpleSSLContext; +import static java.net.http.HttpRequest.*; +import static java.net.http.HttpResponse.*; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * * Basic smoke test for Http/1.1 client + * - basic request response + * - request body POST + * - response body GET + * - redirect + * - chunked request/response + * - SSL + * - proxies + * - 100 continue + * - check keep alive appears to be working + * - cancel of long request + * + * Uses a FileServerHandler serving a couple of known files + * in docs directory. + */ +public class SmokeTest { + static SSLContext ctx; + static HttpServer s1 ; + static HttpsServer s2; + static ExecutorService executor; + static int port; + static int httpsport; + static String httproot; + static String httpsroot; + static HttpClient client; + static ProxyServer proxy; + static int proxyPort; + static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; + static RedirectHandler redirectHandler, redirectHandlerSecure; + static DelayHandler delayHandler; + final static String midSizedFilename = "/files/notsobigfile.txt"; + final static String smallFilename = "/files/smallfile.txt"; + static Path midSizedFile; + static Path smallFile; + static String fileroot; + + static String getFileContent(String path) throws IOException { + FileInputStream fis = new FileInputStream(path); + byte[] buf = new byte[2000]; + StringBuilder sb = new StringBuilder(); + int n; + while ((n=fis.read(buf)) != -1) { + sb.append(new String(buf, 0, n, "US-ASCII")); + } + return sb.toString(); + } + + public static void main(String[] args) throws Exception { + initServer(); + fileroot = System.getProperty ("test.src", ".")+ "/docs"; + midSizedFile = Paths.get(fileroot + midSizedFilename); + smallFile = Paths.get(fileroot + smallFilename); + + client = HttpClient.create() + .sslContext(ctx) + .followRedirects(HttpClient.Redirect.ALWAYS) + .executorService(Executors.newCachedThreadPool()) + .build(); + + try { + test1(httproot + "files/foo.txt", true); + + test1(httproot + "files/foo.txt", false); + test1(httpsroot + "files/foo.txt", true); + test1(httpsroot + "files/foo.txt", false); + test2(httproot + "echo/foo", "This is a short test"); + test2(httpsroot + "echo/foo", "This is a short test"); + + test3(httproot + "redirect/foo.txt"); + test3(httpsroot + "redirect/foo.txt"); + test4(httproot + "files/foo.txt"); + test4(httpsroot + "files/foo.txt"); + test5(httproot + "echo/foo", true); + test5(httpsroot + "echo/foo", true); + test5(httproot + "echo/foo", false); + test5(httpsroot + "echo/foo", false); + + test6(httproot + "echo/foo", true); + test6(httpsroot + "echo/foo", true); + test6(httproot + "echo/foo", false); + test6(httpsroot + "echo/foo", false); + + test7(httproot + "keepalive/foo"); + + test8(httproot + "files/foo.txt", true); + test8(httproot + "files/foo.txt", false); + test8(httpsroot + "files/foo.txt", true); + test8(httpsroot + "files/foo.txt", false); + // disabled test9(); + + test10(httproot + "redirecterror/foo.txt"); + + test10(httpsroot + "redirecterror/foo.txt"); + + test11(httproot + "echo/foo"); + test11(httpsroot + "echo/foo"); + //test12(httproot + "delay/foo", delayHandler); + + } finally { + s1.stop(0); + s2.stop(0); + proxy.close(); + executor.shutdownNow(); + client.executorService().shutdownNow(); + } + } + + static class Auth extends java.net.Authenticator { + volatile int count = 0; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (count++ == 0) { + return new PasswordAuthentication("user", "passwd".toCharArray()); + } else { + return new PasswordAuthentication("user", "goober".toCharArray()); + } + } + int count() { + return count; + } + } + + // Basic test + static void test1(String target, boolean fixedLen) throws Exception { + System.out.print("test1: " + target); + URI uri = new URI(target); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + String body = response.body(asString()); + if (!body.equals("This is foo.txt\r\n")) { + throw new RuntimeException(); + } + + // repeat async + response = builder.GET().responseAsync().join(); + + body = response.body(asString()); + if (!body.equals("This is foo.txt\r\n")) { + throw new RuntimeException(); + } + System.out.println(" OK"); + } + + // POST use echo to check reply + static void test2(String s, String body) throws Exception { + System.out.print("test2: " + s); + URI uri = new URI(s); + + HttpResponse response = client.request(uri) + .body(fromString(body)) + .POST() + .response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } + String reply = response.body(asString()); + if (!reply.equals(body)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + reply + "]"); + } + System.out.println(" OK"); + } + + // Redirect + static void test3(String s) throws Exception { + System.out.print("test3: " + s); + URI uri = new URI(s); + RedirectHandler handler = uri.getScheme().equals("https") + ? redirectHandlerSecure : redirectHandler; + + HttpResponse response = client.request(uri) + .body(noBody()) + .GET() + .response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } else { + response.body(HttpResponse.asFile(Paths.get("redir1.txt"))); + } + + Path downloaded = Paths.get("redir1.txt"); + if (Files.size(downloaded) != Files.size(midSizedFile)) { + throw new RuntimeException("Size mismatch"); + } + + System.out.printf(" (count: %d) ", handler.count()); + // repeat with async api + + handler.reset(); + + response = client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .join(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } else { + response.body(HttpResponse.asFile(Paths.get("redir2.txt"))); + } + + downloaded = Paths.get("redir2.txt"); + if (Files.size(downloaded) != Files.size(midSizedFile)) { + throw new RuntimeException("Size mismatch 2"); + } + System.out.printf(" (count: %d) ", handler.count()); + System.out.println(" OK"); + } + + // Proxies + static void test4(String s) throws Exception { + System.out.print("test4: " + s); + URI uri = new URI(s); + InetSocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", proxyPort); + String filename = fileroot + uri.getPath(); + + HttpClient cl = HttpClient.create() + .proxy(ProxySelector.of(proxyAddr)) + .sslContext(ctx) + .build(); + + CompletableFuture fut = cl.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenCompose((HttpResponse response) -> + response.bodyAsync(asString()) + ); + + String body = fut.get(5, TimeUnit.HOURS); + + String fc = getFileContent(filename); + + if (!body.equals(fc)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + fc + "]"); + } + cl.executorService().shutdownNow(); + System.out.println(" OK"); + } + + // 100 Continue: use echo target + static void test5(String target, boolean fixedLen) throws Exception { + System.out.print("test5: " + target); + URI uri = new URI(target); + String requestBody = generateString(12 * 1024 + 13); + + HttpRequest.Builder builder = client.request(uri) + .expectContinue(true) + .body(fromString(requestBody)); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + String body = response.body(asString()); + + if (!body.equals(requestBody)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + body + "]"); + } + System.out.println(" OK"); + } + + // use echo + static void test6(String target, boolean fixedLen) throws Exception { + System.out.print("test6: " + target); + URI uri = new URI(target); + String requestBody = generateString(12 * 1024 + 3); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } + + String responseBody = response.body(asString()); + + if (responseBody.equals(requestBody)) { + throw new RuntimeException( + "Body mismatch: expected [" + requestBody + "], got [" + responseBody + "]"); + } + System.out.println(" OK"); + } + + @SuppressWarnings("rawtypes") + static void test7(String target) throws Exception { + System.out.print("test7: " + target); + + // First test + URI uri = new URI(target); + for (int i=0; i<4; i++) { + HttpResponse r = client.request(uri) + .body(noBody()) + .GET() + .response(); + String body = r.body(asString()); + if (!body.equals("OK")) { + throw new RuntimeException("Expected OK, got: " + body); + } + } + + // Second test: 4 x parallel + List> futures = new LinkedList<>(); + for (int i=0; i<4; i++) { + futures.add(client.request(uri) + .body(noBody()) + .GET() + .responseAsync()); + } + // all sent? + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + List> futureBodies = new LinkedList<>(); + for (int i=0; i<4; i++) { + futureBodies.add(futures.get(i) + .join() + .bodyAsync(asString())); + } + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + for (CompletableFuture future : futureBodies) { + String body = future.get(); + if (!body.equals("OK")) { + throw new RuntimeException("Expected OK, got: " + body); + } + } + + // Third test: Multiple of 4 parallel requests + BlockingQueue q = new LinkedBlockingQueue<>(); + for (int i=0; i<4; i++) { + client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenApply((HttpResponse resp) -> { + String body = resp.body(asString()); + putQ(q, body); + return body; + }); + } + // we've sent four requests. Now, just send another request + // as each response is received. The idea is to ensure that + // only four sockets ever get used. + + for (int i=0; i<100; i++) { + // block until response received + String body = takeQ(q); + if (!body.equals("OK")) { + throw new RuntimeException(body); + } + client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenApply((HttpResponse resp) -> { + String body1 = resp.body(asString()); + putQ(q, body1); + return body1; + }); + } + // should be four left + for (int i=0; i<4; i++) { + takeQ(q); + } + System.out.println(" OK"); + } + + static String takeQ(BlockingQueue q) { + String r = null; + try { + r = q.take(); + } catch (InterruptedException e) {} + + return r; + } + + static void putQ(BlockingQueue q, String o) { + try { + q.put(o); + } catch (InterruptedException e) { + // can't happen + } + } + + static void test8(String target, boolean fixedLen) throws Exception { + System.out.print("test8: " + target); + URI uri = new URI(target); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + StringBuilder sb = new StringBuilder(); + + InputStream is = response.body(asInputStream()); + int c; + byte[] buf = new byte[2048]; + while ((c = is.read(buf)) != -1) { + for (int i=0; i cf = request.responseAsync(); + request.cancel(); + h.barrier2().await(); + try { + HttpResponse r = cf.get(); + throw new RuntimeException("failed 2"); + } catch (Exception e) { + } + System.out.println(" OK"); + } +*/ + static void delay(int seconds) { + try { + Thread.sleep(seconds * 1000); + } catch (InterruptedException e) { + } + } +/* + // test won't work until sending fully decoupled from receiving in impl + static void test9() throws Exception { + System.out.print("test9: "); + UploadServer up = new UploadServer(1000 * 1000); + int size = up.size(); + String u = "http://127.0.0.1:" + up.port() + "/"; + URI uri = new URI(u); + + HttpRequest request = client + .request(uri) + .body(new HttpRequestBodyProcessor() { + @Override + public ByteBuffer onRequestBodyChunk(ByteBuffer b) throws IOException { + // slow things down + delay(1); + b.position(b.limit()); // fill it + return b; + } + @Override + public long onRequestStart(HttpRequest req) throws IOException { + return size; + } + }) + .PUT(); + + CompletableFuture cf1 = request.sendAsync(); + CompletableFuture cf = request.responseAsync(); + + HttpResponse resp = cf.get(1, TimeUnit.MINUTES); + if (resp.statusCode() != 201) { + throw new RuntimeException("failed: wrong response code"); + } + delay(2); // allow some data to be sent + request.cancel(); + delay(1); + if (up.failed()) { + throw new RuntimeException("failed to cancel request"); + } + System.out.println(" OK"); + } + */ + // Redirect loop: return an error after a certain number of redirects + static void test10(String s) throws Exception { + System.out.print("test10: " + s); + URI uri = new URI(s); + RedirectErrorHandler handler = uri.getScheme().equals("https") + ? redirectErrorHandlerSecure : redirectErrorHandler; + + CompletableFuture cf = client.request(uri) + .body(noBody()) + .GET() + .responseAsync(); + + try { + HttpResponse response = cf.join(); + throw new RuntimeException("Exepected Completion Exception"); + } catch (CompletionException e) { + //System.out.println(e); + } + + System.out.printf(" (Calls %d) ", handler.count()); + System.out.println(" OK"); + } + + static final int NUM = 50; + + static Random random = new Random(); + static final String alphabet = "ABCDEFGHIJKLMNOPQRST"; + + static char randomChar() { + return alphabet.charAt(random.nextInt(alphabet.length())); + } + + static String generateString(int length) { + StringBuilder sb = new StringBuilder(length); + for (int i=0; i= size; + } finally { + try { + ss.close(); + if (s != null) + s.close(); + } catch (IOException e) {} + } + } + } +} + +class RedirectHandler implements HttpHandler { + String root; + volatile int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException + { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers responseHeaders = t.getResponseHeaders(); + + if (count++ < 1) { + responseHeaders.add("Location", root + "/foo/" + count); + } else { + responseHeaders.add("Location", SmokeTest.midSizedFilename); + } + t.sendResponseHeaders(301, -1); + t.close(); + } + + int count() { + return count; + } + + void reset() { + count = 0; + } +} + +class RedirectErrorHandler implements HttpHandler { + String root; + volatile int count = 1; + + RedirectErrorHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle (HttpExchange t) + throws IOException + { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + String redirect = root + "/foo/" + Integer.toString(count); + increment(); + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } +} + +class Util { + static byte[] readAll(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + byte[] result = new byte[0]; + + while (true) { + int n = is.read(buf); + if (n > 0) { + byte[] b1 = new byte[result.length + n]; + System.arraycopy(result, 0, b1, 0, result.length); + System.arraycopy(buf, 0, b1, result.length, n); + result = b1; + } else if (n == -1) { + return result; + } + } + } +} + +class DelayHandler implements HttpHandler { + + CyclicBarrier bar1 = new CyclicBarrier(2); + CyclicBarrier bar2 = new CyclicBarrier(2); + CyclicBarrier bar3 = new CyclicBarrier(2); + + CyclicBarrier barrier1() { + return bar1; + } + + CyclicBarrier barrier2() { + return bar2; + } + + @Override + public synchronized void handle(HttpExchange he) throws IOException { + byte[] buf = Util.readAll(he.getRequestBody()); + try { + bar1.await(); + bar2.await(); + } catch (Exception e) {} + he.sendResponseHeaders(200, -1); // will probably fail + he.close(); + } + +} + +// check for simple hardcoded sequence and use remote address +// to check. +// First 4 requests executed in sequence (should use same connection/address) +// Next 4 requests parallel (should use different addresses) +// Then send 4 requests in parallel x 100 times (same four addresses used all time) + +class KeepAliveHandler implements HttpHandler { + volatile int counter = 0; + + HashSet portSet = new HashSet<>(); + + volatile int[] ports = new int[4]; + + void sleep(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) {} + } + + @Override + public synchronized void handle (HttpExchange t) + throws IOException + { + int remotePort = t.getRemoteAddress().getPort(); + String result = "OK"; + + int n = counter++; + /// First test + if (n < 4) { + ports[n] = remotePort; + } + if (n == 3) { + // check all values in ports[] are the same + if (ports[0] != ports[1] || ports[2] != ports[3] + || ports[0] != ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + // Second test + if (n >=4 && n < 8) { + // delay to ensure ports are different + sleep(500); + ports[n-4] = remotePort; + } + if (n == 7) { + // should be all different + if (ports[0] == ports[1] || ports[2] == ports[3] + || ports[0] == ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + System.out.printf("Ports: %d, %d, %d, %d\n", ports[0], ports[1], ports[2], ports[3]); + } + // setup for third test + for (int i=0; i<4; i++) { + portSet.add(ports[i]); + } + } + // Third test + if (n > 7) { + // just check that port is one of the ones in portSet + if (!portSet.contains(remotePort)) { + System.out.println ("UNEXPECTED REMOTE PORT " + remotePort); + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + byte[] buf = new byte[2048]; + + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + t.sendResponseHeaders(200, result.length()); + OutputStream o = t.getResponseBody(); + o.write(result.getBytes("US-ASCII")); + t.close(); + } +} diff --git a/jdk/test/java/net/httpclient/SplitResponse.java b/jdk/test/java/net/httpclient/SplitResponse.java new file mode 100644 index 00000000000..cf887c19a0f --- /dev/null +++ b/jdk/test/java/net/httpclient/SplitResponse.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 javaapplication16; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +/** + * @test + * @bug 8087112 + * @build Server + * @run main/othervm -Djava.net.HttpClient.log=all SplitResponse + */ + +/** + * Similar test to QuickResponses except that each byte of the response + * is sent in a separate packet, which tests the stability of the implementation + * for receiving unusual packet sizes. + */ +public class SplitResponse { + + static Server server; + + static String response(String body) { + return "HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-length: " + + Integer.toString(body.length()) + + "\r\n\r\n" + body; + } + + static final String responses[] = { + "Lorem ipsum", + "dolor sit amet", + "consectetur adipiscing elit, sed do eiusmod tempor", + "quis nostrud exercitation ullamco", + "laboris nisi", + "ut", + "aliquip ex ea commodo consequat." + + "Duis aute irure dolor in reprehenderit in voluptate velit esse" + + "cillum dolore eu fugiat nulla pariatur.", + "Excepteur sint occaecat cupidatat non proident." + }; + + public static void main(String[] args) throws Exception { + server = new Server(0); + URI uri = new URI(server.getURL()); + + HttpRequest request; + HttpResponse r; + CompletableFuture cf1; + + for (int i=0; i { + try { + int len = s.length(); + for (int i = 0; i < len; i++) { + String onechar = s.substring(i, i + 1); + conn.send(onechar); + Thread.sleep(30); + } + System.out.println("sent"); + } catch (IOException | InterruptedException e) { + } + }); + t.setDaemon(true); + t.start(); + } +} diff --git a/jdk/test/java/net/httpclient/TimeoutTest.java b/jdk/test/java/net/httpclient/TimeoutTest.java new file mode 100644 index 00000000000..d7d2ff224a9 --- /dev/null +++ b/jdk/test/java/net/httpclient/TimeoutTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpTimeoutException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * @test + * @bug 8087112 + * @run main/othervm TimeoutTest + */ + +public class TimeoutTest { + + static int[] timeouts = {6, 4, 8, 6, 6, 4}; + static HttpRequest[] rqs = new HttpRequest[timeouts.length]; + static LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + static volatile boolean error = false; + static ExecutorService executor = Executors.newCachedThreadPool(); + + public static void main(String[] args) throws Exception { + try { + dotest(); + } finally { + HttpClient.getDefault().executorService().shutdownNow(); + executor.shutdownNow(); + } + } + public static void dotest() throws Exception { + System.out.println("Test takes over 40 seconds"); + ServerSocket ss = new ServerSocket(0, 20); + int port = ss.getLocalPort(); + + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/foo"); + int i = 0; + for (int timeout : timeouts) { + HttpRequest request; + (request = rqs[i] = HttpRequest.create(uri) + .timeout(TimeUnit.SECONDS, timeout) + .GET()) + .responseAsync() + .whenComplete((HttpResponse r, Throwable t) -> { + if (!(t.getCause() instanceof HttpTimeoutException)) { + System.out.println("Wrong exception type:" + t.toString()); + error = true; + } + if (t != null) { + queue.add(request); + } + }) + .thenAccept((HttpResponse r) -> { + r.bodyAsync(HttpResponse.ignoreBody()); + }); + i++; + } + + System.out.println("SUBMITTED"); + + checkReturnOrder(); + + if (error) + throw new RuntimeException("Failed"); + + // Repeat blocking in separate threads. Use queue to wait. + System.out.println("DOING BLOCKING"); + + i = 0; + for (int timeout : timeouts) { + HttpRequest req = HttpRequest.create(uri) + .timeout(TimeUnit.SECONDS, timeout) + .GET(); + rqs[i] = req; + executor.execute(() -> { + try { + req.response().body(HttpResponse.ignoreBody()); + } catch (HttpTimeoutException e) { + queue.offer(req); + } catch (IOException | InterruptedException ee) { + error = true; + } + }); + i++; + } + + checkReturnOrder(); + + if (error) + throw new RuntimeException("Failed"); + } + + static void checkReturnOrder() throws InterruptedException { + // wait for exceptions and check order + for (int j = 0; j < timeouts.length; j++) { + HttpRequest req = queue.take(); + switch (j) { + case 0: + case 1: + if (req != rqs[1] && req != rqs[5]) { + System.out.printf("Expected 1 or 5. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + break; + case 2: + case 3: + case 4: + if (req != rqs[0] && req != rqs[3] && req != rqs[4]) { + System.out.printf("Expected r1, r4 or r5. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + break; + case 5: + if (req != rqs[2]) { + System.out.printf("Expected r3. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + } + } + System.out.println("Return order ok"); + } + + static String getRequest(HttpRequest req) { + for (int i=0; i clients = new LinkedList<>(); + static URI uri; + + interface Test { + public void execute() throws IOException, InterruptedException; + } + + static class TestAndResult { + Test test; + boolean result; + + TestAndResult (Test t, boolean result) { + this.test = t; + this.result = result; + } + } + + static TestAndResult test(boolean result, Test t) { + return new TestAndResult(t, result); + } + + static TestAndResult[] tests; + static String testclasses; + static File subdir; + + /** + * The ProxyServer class is compiled by jtreg, but we want to + * move it so it is not on the application claspath. We want to + * load it through a separate classloader so that it has a separate + * protection domain and security permissions. + * + * Its permissions are in the second grant block in each policy file + */ + static void setupProxy() throws IOException, ClassNotFoundException, NoSuchMethodException { + testclasses = System.getProperty("test.classes"); + subdir = new File (testclasses, "proxydir"); + subdir.mkdir(); + + movefile("ProxyServer.class"); + movefile("ProxyServer$Connection.class"); + movefile("ProxyServer$1.class"); + + URL url = subdir.toURL(); + System.out.println("URL for class loader = " + url); + URLClassLoader urlc = new URLClassLoader(new URL[] {url}); + proxyClass = Class.forName("ProxyServer", true, urlc); + proxyConstructor = proxyClass.getConstructor(Integer.class, Boolean.class); + } + + static void movefile(String f) throws IOException { + Path src = Paths.get(testclasses, f); + Path dest = subdir.toPath().resolve(f); + if (!dest.toFile().exists()) { + System.out.printf("moving %s to %s\n", src.toString(), dest.toString()); + Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING); + } else { + System.out.printf("NOT moving %s to %s\n", src.toString(), dest.toString()); + } + } + + static Object getProxy(int port, boolean b) throws Exception { + return proxyConstructor.newInstance(port, b); + } + + static Class proxyClass; + static Constructor proxyConstructor; + + static void setupTests() { + tests = new TestAndResult[]{ + // (0) policy does not have permission for file. Should fail + test(false, () -> { // Policy 0 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (1) policy has permission for file URL + test(true, () -> { //Policy 1 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (2) policy has permission for all file URLs under /files + test(true, () -> { // Policy 2 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (3) policy has permission for first URL but not redirected URL + test(false, () -> { // Policy 3 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (4) policy has permission for both first URL and redirected URL + test(true, () -> { // Policy 4 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (5) policy has permission for redirected but not first URL + test(false, () -> { // Policy 5 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (6) policy has permission for file URL, but not method + test(false, () -> { //Policy 6 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (7) policy has permission for file URL, method, but not header + test(false, () -> { //Policy 7 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .header("X-Foo", "bar") + .GET(); + HttpResponse response = request.response(); + }), + // (8) policy has permission for file URL, method and header + test(true, () -> { //Policy 8 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .header("X-Foo", "bar") + .GET(); + HttpResponse response = request.response(); + }), + // (9) policy has permission for file URL, method and header + test(true, () -> { //Policy 9 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .headers("X-Foo", "bar", "X-Bar", "foo") + .GET(); + HttpResponse response = request.response(); + }), + // (10) policy has permission for destination URL but not for proxy + test(false, () -> { //Policy 10 + directProxyTest(27208, true); + }), + // (11) policy has permission for both destination URL and proxy + test(true, () -> { //Policy 11 + directProxyTest(27301, true); + }), + // (12) policy has permission for both destination URL and proxy + test(false, () -> { //Policy 11 + directProxyTest(28301, false); + }), + // (13) async version of test 0 + test(false, () -> { // Policy 0 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + try { + HttpResponse response = request.responseAsync().get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }), + // (14) async version of test 1 + test(true, () -> { //Policy 1 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + try { + HttpResponse response = request.responseAsync().get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }), + // (15) check that user provided unprivileged code running on a worker + // thread does not gain ungranted privileges. + test(false, () -> { //Policy 12 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + HttpResponse.BodyProcessor stproc = HttpResponse.asString(); + + CompletableFuture cf; + cf = response.bodyAsync(new HttpResponse.BodyProcessor() { + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + // do some mischief here + SecurityManager sm = System.getSecurityManager(); + System.setSecurityManager(null); + System.setSecurityManager(sm); + // problem if we get this far + stproc.onResponseBodyChunk(b); + } + public String onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer fc) throws IOException { + + SecurityManager sm = System.getSecurityManager(); + // should succeed. + sm.checkPermission(new RuntimePermission("foobar")); + return stproc.onResponseBodyStart(contentLength,responseHeaders, fc); + } + public String onResponseComplete() throws IOException { + return stproc.onResponseComplete(); + } + public void onResponseError(Throwable t) { + stproc.onResponseError(t); + } + } + ); + try { + System.out.println("Body = " + cf.get());// should not reach here + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }) + }; + } + + private static void directProxyTest(int proxyPort, boolean samePort) throws IOException, InterruptedException { + Object proxy = null; + try { + proxy = getProxy(proxyPort, true); + } catch (IOException e) { + System.out.println("Cannot bind. Not running test"); + throw new SecurityException("test not run"); + } catch (Exception ee) { + throw new RuntimeException(ee); + } + System.out.println("Proxy port = " + proxyPort); + if (!samePort) + proxyPort++; + + HttpClient cl = HttpClient.create() + .proxy(ProxySelector.of( + new InetSocketAddress("127.0.0.1", proxyPort))) + .build(); + clients.add(cl); + + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = cl.request(u) + .headers("X-Foo", "bar", "X-Bar", "foo") + .GET(); + HttpResponse response = request.response(); + } + + static void runtest(Test r, String policy, boolean succeeds) { + System.out.println("Using policy file: " + policy); + try { + r.execute(); + if (!succeeds) { + System.out.println("FAILED: expected security exception"); + throw new RuntimeException("Failed"); + } + System.out.println (policy + " succeeded as expected"); + } catch (SecurityException e) { + if (succeeds) { + System.out.println("FAILED"); + throw new RuntimeException(e); + } + System.out.println (policy + " threw exception as expected"); + } catch (IOException | InterruptedException ee) { + throw new RuntimeException(ee); + } + } + + public static void main(String[] args) throws Exception { + initServer(); + setupProxy(); + fileroot = System.getProperty ("test.src")+ "/docs"; + int testnum = Integer.parseInt(args[0]); + String policy = args[0]; + + client = HttpClient + .create() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build(); + + clients.add(HttpClient.getDefault()); + clients.add(client); + + try { + setupTests(); + TestAndResult tr = tests[testnum]; + runtest(tr.test, policy, tr.result); + } finally { + s1.stop(0); + //executor.shutdownNow(); + for (HttpClient client : clients) + client.executorService().shutdownNow(); + } + } + + // create Http Server on port range below. So, we can + HttpServer createServer() { + HttpServer server; + for (int i=25800; i<26800; i++) { + InetSocketAddress a = new InetSocketAddress(i); + try { + server = HttpServer.create(a, 0); + return server; + } catch (IOException e) {} + } + return null; + } + + public static void initServer() throws Exception { + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + String root = System.getProperty ("test.src")+ "/docs"; + InetSocketAddress addr = new InetSocketAddress (0); + s1 = HttpServer.create (addr, 0); + if (s1 instanceof HttpsServer) { + throw new RuntimeException ("should not be httpsserver"); + } + HttpHandler h = new FileServerHandler (root); + HttpContext c = s1.createContext ("/files", h); + + HttpHandler h1 = new RedirectHandler ("/redirect"); + HttpContext c1 = s1.createContext ("/redirect", h1); + + executor = Executors.newCachedThreadPool(); + s1.setExecutor (executor); + s1.start(); + + port = s1.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httproot = "http://127.0.0.1:" + port + "/files/"; + redirectroot = "http://127.0.0.1:" + port + "/redirect/"; + uri = new URI(httproot); + fileuri = httproot + "foo.txt"; + } + + static class RedirectHandler implements HttpHandler { + + String root; + int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + System.out.println("Server: " + t.getRequestURI()); + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + increment(); + if (count() == 1) { + Headers map = t.getResponseHeaders(); + String redirect = "/redirect/bar.txt"; + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } else { + String response = "Hello world"; + t.sendResponseHeaders(200, response.length()); + OutputStream os = t.getResponseBody(); + os.write(response.getBytes(StandardCharsets.ISO_8859_1)); + t.close(); + } + } + } +} From 572b48bca55283aa67dc61502792beb2e834e60c Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Thu, 25 Feb 2016 16:10:15 -0800 Subject: [PATCH 136/139] 8145854: SSLContextImpl.statusResponseManager should be generated if required Implement server-side lazy initialization of StatusResponseManagers in the SSLContextImpl class. Reviewed-by: xuelei --- .../sun/security/ssl/ClientHandshaker.java | 9 +- .../sun/security/ssl/SSLContextImpl.java | 33 +- .../sun/security/ssl/ServerHandshaker.java | 43 +- .../net/ssl/Stapling/StapleEnableProps.java | 721 ++++++++++++++++++ 4 files changed, 780 insertions(+), 26 deletions(-) create mode 100644 jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java index 05d5e2f7906..3d2bb763a7b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,9 +81,6 @@ final class ClientHandshaker extends Handshaker { private boolean serverKeyExchangeReceived; - private final boolean enableStatusRequestExtension = - Debug.getBooleanProperty( - "jdk.tls.client.enableStatusRequestExtension", true); private boolean staplingActive = false; private X509Certificate[] deferredCerts; @@ -761,7 +758,7 @@ final class ClientHandshaker extends Handshaker { type == ExtensionType.EXT_STATUS_REQUEST_V2) { // Only enable the stapling feature if the client asserted // these extensions. - if (enableStatusRequestExtension) { + if (sslContext.isStaplingEnabled(true)) { staplingActive = true; } else { fatalSE(Alerts.alert_unexpected_message, "Server set " + @@ -1562,7 +1559,7 @@ final class ClientHandshaker extends Handshaker { } // Add status_request and status_request_v2 extensions - if (enableStatusRequestExtension) { + if (sslContext.isStaplingEnabled(true)) { clientHelloMessage.addCertStatusReqListV2Extension(); clientHelloMessage.addCertStatusRequestExtension(); } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 15b420da172..903f6fb376a 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,11 @@ public abstract class SSLContextImpl extends SSLContextSpi { // DTLS cookie exchange manager private volatile HelloCookieManager helloCookieManager; - private StatusResponseManager statusResponseManager; + private final boolean clientEnableStapling = Debug.getBooleanProperty( + "jdk.tls.client.enableStatusRequestExtension", true); + private final boolean serverEnableStapling = Debug.getBooleanProperty( + "jdk.tls.server.enableStatusRequestExtension", false); + private volatile StatusResponseManager statusResponseManager; SSLContextImpl() { ephemeralKeyManager = new EphemeralKeyManager(); @@ -80,7 +84,6 @@ public abstract class SSLContextImpl extends SSLContextSpi { } } trustManager = chooseTrustManager(tm); - statusResponseManager = new StatusResponseManager(); if (sr == null) { secureRandom = JsseJce.getSecureRandom(); @@ -258,6 +261,18 @@ public abstract class SSLContextImpl extends SSLContextSpi { } StatusResponseManager getStatusResponseManager() { + if (serverEnableStapling && statusResponseManager == null) { + synchronized (this) { + if (statusResponseManager == null) { + if (debug != null && Debug.isOn("sslctx")) { + System.out.println( + "Initializing StatusResponseManager"); + } + statusResponseManager = new StatusResponseManager(); + } + } + } + return statusResponseManager; } @@ -309,6 +324,18 @@ public abstract class SSLContextImpl extends SSLContextSpi { (cipherSuites == getClientDefaultCipherSuiteList()); } + /** + * Return whether client or server side stapling has been enabled + * for this SSLContextImpl + * @param isClient true if the caller is operating in a client side role, + * false if acting as a server. + * @return true if stapling has been enabled for the specified role, false + * otherwise. + */ + boolean isStaplingEnabled(boolean isClient) { + return isClient ? clientEnableStapling : serverEnableStapling; + } + /* * Return the list of all available CipherSuites with a priority of * minPriority or above. diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index 0b8072ff679..eb3484c6c4b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,10 +118,6 @@ final class ServerHandshaker extends Handshaker { LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS, new SSLAlgorithmDecomposer()); - // To switch off the status_request[_v2] extensions - private static final boolean enableStatusRequestExtension = - Debug.getBooleanProperty( - "jdk.tls.server.enableStatusRequestExtension", false); private boolean staplingActive = false; private long statusRespTimeout; @@ -589,7 +585,7 @@ final class ServerHandshaker extends Handshaker { (CertStatusReqListV2Extension)mesg.extensions.get( ExtensionType.EXT_STATUS_REQUEST_V2); // Keep stapling active if at least one of the extensions has been set - staplingActive = enableStatusRequestExtension && + staplingActive = sslContext.isStaplingEnabled(false) && (statReqExt != null || statReqExtV2 != null); /* @@ -932,19 +928,32 @@ final class ServerHandshaker extends Handshaker { } if (statReqType != null && statReqData != null) { - // Next, attempt to obtain status responses StatusResponseManager statRespMgr = sslContext.getStatusResponseManager(); - responseMap = statRespMgr.get(statReqType, statReqData, certs, - statusRespTimeout, TimeUnit.MILLISECONDS); - if (!responseMap.isEmpty()) { - // We now can safely assert status_request[_v2] in our - // ServerHello, and know for certain that we can provide - // responses back to this client for this connection. - if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { - m1.extensions.add(new CertStatusReqExtension()); - } else if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST_V2) { - m1.extensions.add(new CertStatusReqListV2Extension()); + if (statRespMgr != null) { + responseMap = statRespMgr.get(statReqType, statReqData, + certs, statusRespTimeout, TimeUnit.MILLISECONDS); + if (!responseMap.isEmpty()) { + // We now can safely assert status_request[_v2] in our + // ServerHello, and know for certain that we can provide + // responses back to this client for this connection. + if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { + m1.extensions.add(new CertStatusReqExtension()); + } else if (statusRespExt == + ExtensionType.EXT_STATUS_REQUEST_V2) { + m1.extensions.add( + new CertStatusReqListV2Extension()); + } + } + } else { + // This should not happen if stapling is active, but + // if lazy initialization of the StatusResponseManager + // doesn't occur we should turn off stapling. + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Warning: lazy initialization " + + "of the StatusResponseManager failed. " + + "Stapling has been disabled."); + staplingActive = false; } } } diff --git a/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java b/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java new file mode 100644 index 00000000000..7dece5ba724 --- /dev/null +++ b/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8145854 + * @summary SSLContextImpl.statusResponseManager should be generated if required + * @library ../../../../java/security/testlibrary + * @build CertificateBuilder SimpleOCSPServer + * @run main/othervm StapleEnableProps + */ + +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.math.BigInteger; +import java.security.*; +import java.nio.*; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import sun.security.testlibrary.SimpleOCSPServer; +import sun.security.testlibrary.CertificateBuilder; + +public class StapleEnableProps { + + /* + * Enables logging of the SSLEngine operations. + */ + private static final boolean logging = true; + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + + // These two ByteBuffer references will be used to hang onto ClientHello + // messages with and without the status_request[_v2] extensions. These + // will be used in the server-side stapling tests. + private static ByteBuffer cHelloStaple; + private static ByteBuffer cHelloNoStaple; + + // The following items are used to set up the keystores. + private static final String passwd = "passphrase"; + private static final String ROOT_ALIAS = "root"; + private static final String INT_ALIAS = "intermediate"; + private static final String SSL_ALIAS = "ssl"; + + // PKI components we will need for this test + private static KeyManagerFactory kmf; + private static TrustManagerFactory tmf; + private static KeyStore rootKeystore; // Root CA Keystore + private static KeyStore intKeystore; // Intermediate CA Keystore + private static KeyStore serverKeystore; // SSL Server Keystore + private static KeyStore trustStore; // SSL Client trust store + private static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder + private static int rootOcspPort; // Port for root OCSP + private static SimpleOCSPServer intOcsp; // Intermediate CA OCSP server + private static int intOcspPort; // Port for intermediate OCSP + + // A few helpful TLS definitions to make it easier + private static final int HELLO_EXT_STATUS_REQ = 5; + private static final int HELLO_EXT_STATUS_REQ_V2 = 17; + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl"); + } + + // Create the PKI we will use for the test and start the OCSP servers + createPKI(); + + // Set up the KeyManagerFactory and TrustManagerFactory + kmf = KeyManagerFactory.getInstance("PKIX"); + kmf.init(serverKeystore, passwd.toCharArray()); + tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(trustStore); + + // Run the client and server property tests + testClientProp(); + testServerProp(); + + } + + private static void testClientProp() throws Exception { + SSLEngineResult clientResult; + + // Test with the client-side enable property set to true + System.out.println("========================================="); + System.out.println("Client Test 1: " + + "jdk.tls.client.enableStatusRequestExtension = true"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.client.enableStatusRequestExtension", + "true"); + SSLContext ctxStaple = SSLContext.getInstance("TLS"); + ctxStaple.init(null, tmf.getTrustManagers(), null); + SSLEngine engine = ctxStaple.createSSLEngine(); + engine.setUseClientMode(true); + SSLSession session = engine.getSession(); + ByteBuffer clientOut = ByteBuffer.wrap("I'm a Client".getBytes()); + ByteBuffer cTOs = + ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Create and check the ClientHello message + clientResult = engine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + if (clientResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + clientResult.getStatus()); + } + cTOs.flip(); + System.out.println(dumpHexBytes(cTOs)); + checkClientHello(cTOs, true, true); + cHelloStaple = cTOs; + + // Test with the property set to false + System.out.println("========================================="); + System.out.println("Client Test 2: " + + "jdk.tls.client.enableStatusRequestExtension = false"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.client.enableStatusRequestExtension", + "false"); + SSLContext ctxNoStaple = SSLContext.getInstance("TLS"); + ctxNoStaple.init(null, tmf.getTrustManagers(), null); + engine = ctxNoStaple.createSSLEngine(); + engine.setUseClientMode(true); + session = engine.getSession(); + cTOs = ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Create and check the ClientHello message + clientResult = engine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + if (clientResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + clientResult.getStatus()); + } + cTOs.flip(); + System.out.println(dumpHexBytes(cTOs)); + checkClientHello(cTOs, false, false); + cHelloNoStaple = cTOs; + } + + private static void testServerProp() throws Exception { + SSLEngineResult serverResult; + HandshakeStatus hsStat; + + // Test with the server-side enable property set to true + System.out.println("========================================="); + System.out.println("Server Test 1: " + + "jdk.tls.server.enableStatusRequestExtension = true"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.server.enableStatusRequestExtension", + "true"); + SSLContext ctxStaple = SSLContext.getInstance("TLS"); + ctxStaple.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + SSLEngine engine = ctxStaple.createSSLEngine(); + engine.setUseClientMode(false); + SSLSession session = engine.getSession(); + ByteBuffer serverOut = ByteBuffer.wrap("I'm a Server".getBytes()); + ByteBuffer serverIn = + ByteBuffer.allocate(session.getApplicationBufferSize() + 50); + ByteBuffer sTOc = + ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Consume the client hello + serverResult = engine.unwrap(cHelloStaple, serverIn); + log("server unwrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Server unwrap got status: " + + serverResult.getStatus()); + } else if (serverResult.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new SSLException("Server unwrap expected NEED_TASK, got: " + + serverResult.getHandshakeStatus()); + } + runDelegatedTasks(serverResult, engine); + if (engine.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_WRAP) { + throw new SSLException("Expected NEED_WRAP, got: " + + engine.getHandshakeStatus()); + } + + // Generate a TLS record with the ServerHello + serverResult = engine.wrap(serverOut, sTOc); + log("client wrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + serverResult.getStatus()); + } + sTOc.flip(); + System.out.println(dumpHexBytes(sTOc)); + checkServerHello(sTOc, false, true); + + // Flip the client hello so we can reuse it in the next test. + cHelloStaple.flip(); + + // Test with the server-side enable property set to false + System.out.println("========================================="); + System.out.println("Server Test 2: " + + "jdk.tls.server.enableStatusRequestExtension = false"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.server.enableStatusRequestExtension", + "false"); + SSLContext ctxNoStaple = SSLContext.getInstance("TLS"); + ctxNoStaple.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + engine = ctxNoStaple.createSSLEngine(); + engine.setUseClientMode(false); + session = engine.getSession(); + serverIn = ByteBuffer.allocate(session.getApplicationBufferSize() + 50); + sTOc = ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Consume the client hello + serverResult = engine.unwrap(cHelloStaple, serverIn); + log("server unwrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Server unwrap got status: " + + serverResult.getStatus()); + } else if (serverResult.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new SSLException("Server unwrap expected NEED_TASK, got: " + + serverResult.getHandshakeStatus()); + } + runDelegatedTasks(serverResult, engine); + if (engine.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_WRAP) { + throw new SSLException("Expected NEED_WRAP, got: " + + engine.getHandshakeStatus()); + } + + // Generate a TLS record with the ServerHello + serverResult = engine.wrap(serverOut, sTOc); + log("client wrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + serverResult.getStatus()); + } + sTOc.flip(); + System.out.println(dumpHexBytes(sTOc)); + checkServerHello(sTOc, false, false); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } + + /** + * Dump a ByteBuffer as a hexdump to stdout. The dumping routine will + * start at the current position of the buffer and run to its limit. + * After completing the dump, the position will be returned to its + * starting point. + * + * @param data the ByteBuffer to dump to stdout. + * + * @return the hexdump of the byte array. + */ + private static String dumpHexBytes(ByteBuffer data) { + StringBuilder sb = new StringBuilder(); + if (data != null) { + int i = 0; + data.mark(); + while (data.hasRemaining()) { + if (i % 16 == 0 && i != 0) { + sb.append("\n"); + } + sb.append(String.format("%02X ", data.get())); + i++; + } + data.reset(); + } + + return sb.toString(); + } + + /** + * Tests the ClientHello for the presence (or not) of the status_request + * and status_request_v2 hello extensions. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the TLS record + * containing the ClientHello and contains the entire hello message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. If an exception is + * thrown the position at the time of the exception will be preserved. + * + * @param data the ByteBuffer containing the ClientHello bytes + * @param statReqPresent true if the status_request hello extension should + * be present. + * @param statReqV2Present true if the status_request_v2 hello extension + * should be present. + * + * @throws SSLException if the presence or lack of either the + * status_request or status_request_v2 extensions is inconsistent with + * the expected settings in the statReqPresent or statReqV2Present + * parameters. + */ + private static void checkClientHello(ByteBuffer data, + boolean statReqPresent, boolean statReqV2Present) + throws SSLException { + boolean hasV1 = false; + boolean hasV2 = false; + Objects.requireNonNull(data); + data.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(data.get()); + int ver_major = Byte.toUnsignedInt(data.get()); + int ver_minor = Byte.toUnsignedInt(data.get()); + int recLen = Short.toUnsignedInt(data.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > data.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + data.remaining()); + } + + // Grab the handshake message header. + int msgHdr = data.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + // More simple sanity checks + if (msgType != 1) { + throw new SSLException("Not a ClientHello: Type = " + msgType); + } + + // Skip over the protocol version and client random + data.position(data.position() + 34); + + // Jump past the session ID (if there is one) + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Jump past the cipher suites + int csLen = Short.toUnsignedInt(data.getShort()); + if (csLen != 0) { + data.position(data.position() + csLen); + } + + // ...and the compression + int compLen = Byte.toUnsignedInt(data.get()); + if (compLen != 0) { + data.position(data.position() + compLen); + } + + // Now for the fun part. Go through the extensions and look + // for the two status request exts. + int extsLen = Short.toUnsignedInt(data.getShort()); + while (data.hasRemaining()) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + hasV1 |= (extType == HELLO_EXT_STATUS_REQ); + hasV2 |= (extType == HELLO_EXT_STATUS_REQ_V2); + data.position(data.position() + extLen); + } + + if (hasV1 != statReqPresent) { + throw new SSLException("The status_request extension is " + + "inconsistent with the expected result: expected = " + + statReqPresent + ", actual = " + hasV1); + } else if (hasV2 != statReqV2Present) { + throw new SSLException("The status_request_v2 extension is " + + "inconsistent with the expected result: expected = " + + statReqV2Present + ", actual = " + hasV2); + } + + // We should be at the end of the ClientHello + data.reset(); + } + + /** + * Tests the ServerHello for the presence (or not) of the status_request + * or status_request_v2 hello extension. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the TLS record + * containing the ServerHello and contains the entire hello message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. If an exception is + * thrown the position at the time of the exception will be preserved. + * + * @param statReqPresent true if the status_request hello extension should + * be present. + * @param statReqV2Present true if the status_request_v2 hello extension + * should be present. + * + * @throws SSLException if the presence or lack of either the + * status_request or status_request_v2 extensions is inconsistent with + * the expected settings in the statReqPresent or statReqV2Present + * parameters. + */ + private static void checkServerHello(ByteBuffer data, + boolean statReqPresent, boolean statReqV2Present) + throws SSLException { + boolean hasV1 = false; + boolean hasV2 = false; + Objects.requireNonNull(data); + int startPos = data.position(); + data.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(data.get()); + int ver_major = Byte.toUnsignedInt(data.get()); + int ver_minor = Byte.toUnsignedInt(data.get()); + int recLen = Short.toUnsignedInt(data.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > data.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + data.remaining()); + } + + // Grab the handshake message header. + int msgHdr = data.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + // More simple sanity checks + if (msgType != 2) { + throw new SSLException("Not a ServerHello: Type = " + msgType); + } + + // Skip over the protocol version and server random + data.position(data.position() + 34); + + // Jump past the session ID + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Skip the cipher suite and compression method + data.position(data.position() + 3); + + // Go through the extensions and look for the request extension + // expected by the caller. + int extsLen = Short.toUnsignedInt(data.getShort()); + while (data.position() < recLen + startPos + 5) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + hasV1 |= (extType == HELLO_EXT_STATUS_REQ); + hasV2 |= (extType == HELLO_EXT_STATUS_REQ_V2); + data.position(data.position() + extLen); + } + + if (hasV1 != statReqPresent) { + throw new SSLException("The status_request extension is " + + "inconsistent with the expected result: expected = " + + statReqPresent + ", actual = " + hasV1); + } else if (hasV2 != statReqV2Present) { + throw new SSLException("The status_request_v2 extension is " + + "inconsistent with the expected result: expected = " + + statReqV2Present + ", actual = " + hasV2); + } + + // Reset the position to the initial spot at the start of this method. + data.reset(); + } + + /** + * Creates the PKI components necessary for this test, including + * Root CA, Intermediate CA and SSL server certificates, the keystores + * for each entity, a client trust store, and starts the OCSP responders. + */ + private static void createPKI() throws Exception { + CertificateBuilder cbld = new CertificateBuilder(); + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(2048); + KeyStore.Builder keyStoreBuilder = + KeyStore.Builder.newInstance("PKCS12", null, + new KeyStore.PasswordProtection(passwd.toCharArray())); + + // Generate Root, IntCA, EE keys + KeyPair rootCaKP = keyGen.genKeyPair(); + log("Generated Root CA KeyPair"); + KeyPair intCaKP = keyGen.genKeyPair(); + log("Generated Intermediate CA KeyPair"); + KeyPair sslKP = keyGen.genKeyPair(); + log("Generated SSL Cert KeyPair"); + + // Set up the Root CA Cert + cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany"); + cbld.setPublicKey(rootCaKP.getPublic()); + cbld.setSerialNumber(new BigInteger("1")); + // Make a 3 year validity starting from 60 days ago + long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60); + long end = start + TimeUnit.DAYS.toMillis(1085); + cbld.setValidity(new Date(start), new Date(end)); + addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic()); + addCommonCAExts(cbld); + // Make our Root CA Cert! + X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(), + "SHA256withRSA"); + log("Root CA Created:\n" + certInfo(rootCert)); + + // Now build a keystore and add the keys and cert + rootKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] rootChain = {rootCert}; + rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(), + passwd.toCharArray(), rootChain); + + // Now fire up the OCSP responder + rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null); + rootOcsp.enableLog(logging); + rootOcsp.setNextUpdateInterval(3600); + rootOcsp.start(); + Thread.sleep(1000); // Give the server a second to start up + rootOcspPort = rootOcsp.getPort(); + String rootRespURI = "http://localhost:" + rootOcspPort; + log("Root OCSP Responder URI is " + rootRespURI); + + // Now that we have the root keystore and OCSP responder we can + // create our intermediate CA. + cbld.reset(); + cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany"); + cbld.setPublicKey(intCaKP.getPublic()); + cbld.setSerialNumber(new BigInteger("100")); + // Make a 2 year validity starting from 30 days ago + start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30); + end = start + TimeUnit.DAYS.toMillis(730); + cbld.setValidity(new Date(start), new Date(end)); + addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic()); + addCommonCAExts(cbld); + cbld.addAIAExt(Collections.singletonList(rootRespURI)); + // Make our Intermediate CA Cert! + X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(), + "SHA256withRSA"); + log("Intermediate CA Created:\n" + certInfo(intCaCert)); + + // Provide intermediate CA cert revocation info to the Root CA + // OCSP responder. + Map revInfo = + new HashMap<>(); + revInfo.put(intCaCert.getSerialNumber(), + new SimpleOCSPServer.CertStatusInfo( + SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)); + rootOcsp.updateStatusDb(revInfo); + + // Now build a keystore and add the keys, chain and root cert as a TA + intKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] intChain = {intCaCert, rootCert}; + intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(), + passwd.toCharArray(), intChain); + intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert); + + // Now fire up the Intermediate CA OCSP responder + intOcsp = new SimpleOCSPServer(intKeystore, passwd, + INT_ALIAS, null); + intOcsp.enableLog(logging); + intOcsp.setNextUpdateInterval(3600); + intOcsp.start(); + Thread.sleep(1000); + intOcspPort = intOcsp.getPort(); + String intCaRespURI = "http://localhost:" + intOcspPort; + log("Intermediate CA OCSP Responder URI is " + intCaRespURI); + + // Last but not least, let's make our SSLCert and add it to its own + // Keystore + cbld.reset(); + cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany"); + cbld.setPublicKey(sslKP.getPublic()); + cbld.setSerialNumber(new BigInteger("4096")); + // Make a 1 year validity starting from 7 days ago + start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7); + end = start + TimeUnit.DAYS.toMillis(365); + cbld.setValidity(new Date(start), new Date(end)); + + // Add extensions + addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic()); + boolean[] kuBits = {true, false, true, false, false, false, + false, false, false}; + cbld.addKeyUsageExt(kuBits); + List ekuOids = new ArrayList<>(); + ekuOids.add("1.3.6.1.5.5.7.3.1"); + ekuOids.add("1.3.6.1.5.5.7.3.2"); + cbld.addExtendedKeyUsageExt(ekuOids); + cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost")); + cbld.addAIAExt(Collections.singletonList(intCaRespURI)); + // Make our SSL Server Cert! + X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(), + "SHA256withRSA"); + log("SSL Certificate Created:\n" + certInfo(sslCert)); + + // Provide SSL server cert revocation info to the Intermeidate CA + // OCSP responder. + revInfo = new HashMap<>(); + revInfo.put(sslCert.getSerialNumber(), + new SimpleOCSPServer.CertStatusInfo( + SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)); + intOcsp.updateStatusDb(revInfo); + + // Now build a keystore and add the keys, chain and root cert as a TA + serverKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] sslChain = {sslCert, intCaCert, rootCert}; + serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(), + passwd.toCharArray(), sslChain); + serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert); + + // And finally a Trust Store for the client + trustStore = keyStoreBuilder.getKeyStore(); + trustStore.setCertificateEntry(ROOT_ALIAS, rootCert); + } + + private static void addCommonExts(CertificateBuilder cbld, + PublicKey subjKey, PublicKey authKey) throws IOException { + cbld.addSubjectKeyIdExt(subjKey); + cbld.addAuthorityKeyIdExt(authKey); + } + + private static void addCommonCAExts(CertificateBuilder cbld) + throws IOException { + cbld.addBasicConstraintsExt(true, true, -1); + // Set key usage bits for digitalSignature, keyCertSign and cRLSign + boolean[] kuBitSettings = {true, false, false, false, false, true, + true, false, false}; + cbld.addKeyUsageExt(kuBitSettings); + } + + /** + * Helper routine that dumps only a few cert fields rather than + * the whole toString() output. + * + * @param cert an X509Certificate to be displayed + * + * @return the String output of the issuer, subject and + * serial number + */ + private static String certInfo(X509Certificate cert) { + StringBuilder sb = new StringBuilder(); + sb.append("Issuer: ").append(cert.getIssuerX500Principal()). + append("\n"); + sb.append("Subject: ").append(cert.getSubjectX500Principal()). + append("\n"); + sb.append("Serial: ").append(cert.getSerialNumber()).append("\n"); + return sb.toString(); + } +} From 39cfbc6593a4048772a438e2a468b7f312acfee5 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Fri, 26 Feb 2016 09:55:14 +0800 Subject: [PATCH 137/139] 8150608: Mark BashStreams.java as intermittently failing and put to ProblemList Reviewed-by: bpb, rriggs --- jdk/test/ProblemList.txt | 3 +++ jdk/test/java/nio/charset/coders/BashStreams.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5b07bb2d65f..8e1c6a6a1e1 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -200,6 +200,9 @@ java/nio/channels/Selector/OutOfBand.java macosx-all java/nio/file/WatchService/Basic.java solaris-all java/nio/file/WatchService/LotsOfEvents.java solaris-all +# 8149712 +java/nio/charset/coders/BashStreams.java generic-all + ############################################################################ # jdk_rmi diff --git a/jdk/test/java/nio/charset/coders/BashStreams.java b/jdk/test/java/nio/charset/coders/BashStreams.java index 15ea14c3ddf..1658021210b 100644 --- a/jdk/test/java/nio/charset/coders/BashStreams.java +++ b/jdk/test/java/nio/charset/coders/BashStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * @summary Stochastic test of charset-based streams - * @key randomness + * @key randomness intermittent */ import java.io.*; From 2435cd24eff54a88739986a6133ff7af1085140c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 26 Feb 2016 06:03:12 +0100 Subject: [PATCH 138/139] 8150497: 32 jshell tests failed on Windows 32 bit Reviewed-by: darcy, tbell --- jdk/make/lib/Lib-jdk.jdi.gmk | 1 + jdk/make/lib/Lib-jdk.jdwp.agent.gmk | 1 + jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c | 2 +- .../jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk index bb1edfd1c23..f74b1c209a6 100644 --- a/jdk/make/lib/Lib-jdk.jdi.gmk +++ b/jdk/make/lib/Lib-jdk.jdi.gmk @@ -47,6 +47,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SHMEM_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ + LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS := $(JDKLIB_LIBS), \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 84c05ba6368..fb5de3e1f24 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -46,6 +46,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ + LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS_linux := -lpthread, \ LIBS_solaris := -lnsl -lsocket -lc, \ LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib, \ diff --git a/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c b/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c index 1b42ad4d12c..81419a9d6a7 100644 --- a/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c +++ b/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c @@ -338,7 +338,7 @@ shmemGetLastError(jdwpTransportEnv* env, char **msgP) return JDWPTRANSPORT_ERROR_NONE; } -JNIEXPORT jint JNICALL +jint JNICALL jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, jint version, jdwpTransportEnv** result) { diff --git a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c index bcd21400ad2..9c86b5a2a27 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c @@ -784,7 +784,7 @@ socketTransport_getLastError(jdwpTransportEnv* env, char** msgP) { return JDWPTRANSPORT_ERROR_NONE; } -JNIEXPORT jint JNICALL +jint JNICALL jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, jint version, jdwpTransportEnv** result) { From ae7478607aaae37e27c997f779694cda6d5e3ba9 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Fri, 26 Feb 2016 12:11:28 +0100 Subject: [PATCH 139/139] 8150533: Test java/util/logging/LogManagerAppContextDeadlock.java times out intermittently This is a test bug caused by a Logger being garbage collected too early. Reviewed-by: darcy --- .../java/util/logging/LogManagerAppContextDeadlock.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java b/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java index 2f1641f49e3..f54eb2a7a5c 100644 --- a/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java +++ b/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java @@ -141,6 +141,7 @@ public class LogManagerAppContextDeadlock { t1.setDaemon(true); t1.start(); Thread t2 = new Thread() { + public Object logger; public void run() { sem3.release(); try { @@ -151,7 +152,10 @@ public class LogManagerAppContextDeadlock { Thread.interrupted(); } System.out.println("Logger.getLogger(name).info(name)"); - Logger.getLogger(test.name());//.info(name); + // stick the logger in an instance variable to prevent it + // from being garbage collected before the main thread + // calls LogManager.getLogger() below. + logger = Logger.getLogger(test.name());//.info(name); System.out.println("Done: Logger.getLogger(name).info(name)"); } };