From e9f0b9af4a914228ab4bb70d779649010264763b Mon Sep 17 00:00:00 2001
From: Jungwoo Ha
Date: Wed, 16 Oct 2013 15:14:37 -0700
Subject: [PATCH 001/110] 8024954: CMS: CMSClassUnloadingMaxInterval is not
implemented correctly. This change is also part of the fix for 8024483
Reviewed-by: mgerdin, brutisso, tschatzl
---
.../concurrentMarkSweepGeneration.cpp | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
index bf4ac21e346..97437bfafe2 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
@@ -594,9 +594,9 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
_verification_mark_bm(0, Mutex::leaf + 1, "CMS_verification_mark_bm_lock"),
_completed_initialization(false),
_collector_policy(cp),
- _should_unload_classes(false),
+ _should_unload_classes(CMSClassUnloadingEnabled),
_concurrent_cycles_since_last_unload(0),
- _roots_scanning_options(0),
+ _roots_scanning_options(SharedHeap::SO_None),
_inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
_intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding),
_gc_tracer_cm(new (ResourceObj::C_HEAP, mtGC) CMSTracer()),
@@ -788,14 +788,6 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
&& _survivor_chunk_index == 0),
"Error");
- // Choose what strong roots should be scanned depending on verification options
- if (!CMSClassUnloadingEnabled) {
- // If class unloading is disabled we want to include all classes into the root set.
- add_root_scanning_option(SharedHeap::SO_AllClasses);
- } else {
- add_root_scanning_option(SharedHeap::SO_SystemClasses);
- }
-
NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;)
_gc_counters = new CollectorCounters("CMS", 1);
_completed_initialization = true;
@@ -3310,7 +3302,10 @@ void CMSCollector::setup_cms_unloading_and_verification_state() {
|| VerifyBeforeExit;
const int rso = SharedHeap::SO_Strings | SharedHeap::SO_CodeCache;
+ // We set the proper root for this CMS cycle here.
if (should_unload_classes()) { // Should unload classes this cycle
+ remove_root_scanning_option(SharedHeap::SO_AllClasses);
+ add_root_scanning_option(SharedHeap::SO_SystemClasses);
remove_root_scanning_option(rso); // Shrink the root set appropriately
set_verifying(should_verify); // Set verification state for this cycle
return; // Nothing else needs to be done at this time
@@ -3318,6 +3313,9 @@ void CMSCollector::setup_cms_unloading_and_verification_state() {
// Not unloading classes this cycle
assert(!should_unload_classes(), "Inconsitency!");
+ remove_root_scanning_option(SharedHeap::SO_SystemClasses);
+ add_root_scanning_option(SharedHeap::SO_AllClasses);
+
if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) {
// Include symbols, strings and code cache elements to prevent their resurrection.
add_root_scanning_option(rso);
From 1123a5596ce984f13e4385cffbe246cd12fa67fa Mon Sep 17 00:00:00 2001
From: Jesper Wilhelmsson
Date: Mon, 21 Oct 2013 18:51:37 +0200
Subject: [PATCH 002/110] 8026851: Remove unnecessary code in GenRemSet
Removed the GenRemSet::rem_set_name() since we only have one remset.
Reviewed-by: stefank, mgerdin, tschatzl
---
hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp | 2 +-
hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp | 2 --
hotspot/src/share/vm/memory/collectorPolicy.cpp | 1 -
hotspot/src/share/vm/memory/collectorPolicy.hpp | 2 --
4 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index 92eee2e8eb9..ad1dce1750b 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -320,7 +320,7 @@ G1CollectorPolicy::G1CollectorPolicy() :
void G1CollectorPolicy::initialize_flags() {
_min_alignment = HeapRegion::GrainBytes;
- size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name());
+ size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
_max_alignment = MAX3(card_table_alignment, _min_alignment, page_size);
if (SurvivorRatio < 1) {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
index a497f2fa3b6..d5bdc08698f 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
@@ -665,8 +665,6 @@ public:
BarrierSet::Name barrier_set_name() { return BarrierSet::G1SATBCTLogging; }
- GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; }
-
bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0);
// Record the start and end of an evacuation pause.
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp
index a3c466327ef..d6c4afe2f01 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp
@@ -105,7 +105,6 @@ bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) {
GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap,
int max_covered_regions) {
- assert(rem_set_name() == GenRemSet::CardTable, "unrecognized GenRemSet::Name");
return new CardTableRS(whole_heap, max_covered_regions);
}
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp
index 42976b34563..a86f45c54d7 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.hpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp
@@ -151,7 +151,6 @@ class CollectorPolicy : public CHeapObj {
virtual BarrierSet::Name barrier_set_name() = 0;
- virtual GenRemSet::Name rem_set_name() = 0;
// Create the remembered set (to cover the given reserved region,
// allowing breaking up into at most "max_covered_regions").
@@ -303,7 +302,6 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
int number_of_generations() { return 2; }
BarrierSet::Name barrier_set_name() { return BarrierSet::CardTableModRef; }
- GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; }
virtual CollectorPolicy::Name kind() {
return CollectorPolicy::TwoGenerationCollectorPolicyKind;
From 5976b6915a7936491afed94515031cded77e83c2 Mon Sep 17 00:00:00 2001
From: Jesper Wilhelmsson
Date: Mon, 21 Oct 2013 18:52:13 +0200
Subject: [PATCH 003/110] 8026852: Use restricted_align_down in collector
policy code
Moved restricted_align_down to globalDefinitions and renamed it align_size_down_bounded
Reviewed-by: stefank, mgerdin, tschatzl
---
hotspot/src/share/vm/memory/collectorPolicy.cpp | 14 +++-----------
hotspot/src/share/vm/memory/metaspace.cpp | 15 +++++----------
.../src/share/vm/utilities/globalDefinitions.hpp | 7 +++++++
3 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp
index d6c4afe2f01..585c7d06cab 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp
@@ -146,11 +146,7 @@ size_t CollectorPolicy::compute_max_alignment() {
// GenCollectorPolicy methods.
size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
- size_t x = base_size / (NewRatio+1);
- size_t new_gen_size = x > _min_alignment ?
- align_size_down(x, _min_alignment) :
- _min_alignment;
- return new_gen_size;
+ return align_size_down_bounded(base_size / (NewRatio + 1), _min_alignment);
}
size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
@@ -410,15 +406,11 @@ bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
if ((heap_size < (*gen0_size_ptr + min_gen1_size)) &&
(heap_size >= min_gen1_size + _min_alignment)) {
// Adjust gen0 down to accommodate min_gen1_size
- *gen0_size_ptr = heap_size - min_gen1_size;
- *gen0_size_ptr =
- MAX2((uintx)align_size_down(*gen0_size_ptr, _min_alignment), _min_alignment);
+ *gen0_size_ptr = align_size_down_bounded(heap_size - min_gen1_size, _min_alignment);
assert(*gen0_size_ptr > 0, "Min gen0 is too large");
result = true;
} else {
- *gen1_size_ptr = heap_size - *gen0_size_ptr;
- *gen1_size_ptr =
- MAX2((uintx)align_size_down(*gen1_size_ptr, _min_alignment), _min_alignment);
+ *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _min_alignment);
}
}
return result;
diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp
index 1877967408d..7ab68dd1ea7 100644
--- a/hotspot/src/share/vm/memory/metaspace.cpp
+++ b/hotspot/src/share/vm/memory/metaspace.cpp
@@ -2965,11 +2965,6 @@ void Metaspace::initialize_class_space(ReservedSpace rs) {
#endif
-// Align down. If the aligning result in 0, return 'alignment'.
-static size_t restricted_align_down(size_t size, size_t alignment) {
- return MAX2(alignment, align_size_down_(size, alignment));
-}
-
void Metaspace::ergo_initialize() {
if (DumpSharedSpaces) {
// Using large pages when dumping the shared archive is currently not implemented.
@@ -2992,13 +2987,13 @@ void Metaspace::ergo_initialize() {
// Ideally, we would be able to set the default value of MaxMetaspaceSize in
// globals.hpp to the aligned value, but this is not possible, since the
// alignment depends on other flags being parsed.
- MaxMetaspaceSize = restricted_align_down(MaxMetaspaceSize, _reserve_alignment);
+ MaxMetaspaceSize = align_size_down_bounded(MaxMetaspaceSize, _reserve_alignment);
if (MetaspaceSize > MaxMetaspaceSize) {
MetaspaceSize = MaxMetaspaceSize;
}
- MetaspaceSize = restricted_align_down(MetaspaceSize, _commit_alignment);
+ MetaspaceSize = align_size_down_bounded(MetaspaceSize, _commit_alignment);
assert(MetaspaceSize <= MaxMetaspaceSize, "MetaspaceSize should be limited by MaxMetaspaceSize");
@@ -3006,10 +3001,10 @@ void Metaspace::ergo_initialize() {
vm_exit_during_initialization("Too small initial Metaspace size");
}
- MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, _commit_alignment);
- MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, _commit_alignment);
+ MinMetaspaceExpansion = align_size_down_bounded(MinMetaspaceExpansion, _commit_alignment);
+ MaxMetaspaceExpansion = align_size_down_bounded(MaxMetaspaceExpansion, _commit_alignment);
- CompressedClassSpaceSize = restricted_align_down(CompressedClassSpaceSize, _reserve_alignment);
+ CompressedClassSpaceSize = align_size_down_bounded(CompressedClassSpaceSize, _reserve_alignment);
set_class_metaspace_size(CompressedClassSpaceSize);
}
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp
index 06a32dc9037..c558574ebbd 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp
@@ -458,6 +458,13 @@ 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) {
+ size_t aligned_size = align_size_down_(size, alignment);
+ return aligned_size > 0 ? aligned_size : alignment;
+}
+
// Clamp an address to be within a specific page
// 1. If addr is on the page it is returned as is
// 2. If addr is above the page_address the start of the *next* page will be returned
From 9705a6e3f94aee2f8862d84d71df4a94b9c3d3f8 Mon Sep 17 00:00:00 2001
From: Jesper Wilhelmsson
Date: Mon, 21 Oct 2013 18:56:20 +0200
Subject: [PATCH 004/110] 8026853: Prepare GC code for collector policy
regression fix
Cleanup related to the NewSize and MaxNewSize bugs
Reviewed-by: tschatzl, jcoomes, ehelin
---
.../g1/g1CollectorPolicy.hpp | 1 -
.../vm/gc_implementation/g1/g1RemSet.cpp | 5 ----
.../parallelScavenge/asPSOldGen.cpp | 3 --
.../parallelScavenge/asPSYoungGen.cpp | 3 --
.../parallelScavenge/parallelScavengeHeap.hpp | 28 +++++++++----------
.../parallelScavenge/psAdaptiveSizePolicy.cpp | 3 +-
.../src/share/vm/memory/collectorPolicy.cpp | 15 +++++-----
.../src/share/vm/memory/collectorPolicy.hpp | 17 +++++++----
.../src/share/vm/memory/genCollectedHeap.cpp | 6 ----
.../src/share/vm/memory/genCollectedHeap.hpp | 4 ---
hotspot/src/share/vm/memory/universe.cpp | 2 +-
hotspot/src/share/vm/runtime/arguments.cpp | 7 +++--
12 files changed, 39 insertions(+), 55 deletions(-)
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
index d5bdc08698f..037876e07e7 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
@@ -217,7 +217,6 @@ private:
return _during_marking;
}
-private:
enum PredictionConstants {
TruncatedSeqLength = 10
};
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
index 0ed37e6c5a5..a11be17ef53 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
@@ -377,11 +377,6 @@ void G1RemSet::prepare_for_oops_into_collection_set_do() {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
dcqs.concatenate_logs();
- if (G1CollectedHeap::use_parallel_gc_threads()) {
- // Don't set the number of workers here. It will be set
- // when the task is run
- // _seq_task->set_n_termination((int)n_workers());
- }
guarantee( _cards_scanned == NULL, "invariant" );
_cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
for (uint i = 0; i < n_workers(); ++i) {
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp
index 39f5835ffe5..6f7026e5a0c 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp
@@ -54,7 +54,6 @@ ASPSOldGen::ASPSOldGen(size_t initial_size,
int level) :
PSOldGen(initial_size, min_size, size_limit, gen_name, level),
_gen_size_limit(size_limit)
-
{}
ASPSOldGen::ASPSOldGen(PSVirtualSpace* vs,
@@ -65,13 +64,11 @@ ASPSOldGen::ASPSOldGen(PSVirtualSpace* vs,
int level) :
PSOldGen(initial_size, min_size, size_limit, gen_name, level),
_gen_size_limit(size_limit)
-
{
_virtual_space = vs;
}
void ASPSOldGen::initialize_work(const char* perf_data_name, int level) {
-
PSOldGen::initialize_work(perf_data_name, level);
// The old gen can grow to gen_size_limit(). _reserve reflects only
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
index 73b63043b71..a7b2eb28ef2 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
@@ -70,7 +70,6 @@ void ASPSYoungGen::initialize(ReservedSpace rs, size_t alignment) {
}
size_t ASPSYoungGen::available_for_expansion() {
-
size_t current_committed_size = virtual_space()->committed_size();
assert((gen_size_limit() >= current_committed_size),
"generation size limit is wrong");
@@ -85,7 +84,6 @@ size_t ASPSYoungGen::available_for_expansion() {
// Future implementations could check the survivors and if to_space is in the
// right place (below from_space), take a chunk from to_space.
size_t ASPSYoungGen::available_for_contraction() {
-
size_t uncommitted_bytes = virtual_space()->uncommitted_size();
if (uncommitted_bytes != 0) {
return uncommitted_bytes;
@@ -121,7 +119,6 @@ size_t ASPSYoungGen::available_for_contraction() {
gclog_or_tty->print_cr(" gen_avail %d K", gen_avail/K);
}
return result_aligned;
-
}
return 0;
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
index 4e458efa903..2ef42c86660 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
@@ -35,7 +35,6 @@
#include "utilities/ostream.hpp"
class AdjoiningGenerations;
-class CollectorPolicy;
class GCHeapSummary;
class GCTaskManager;
class GenerationSizer;
@@ -50,8 +49,8 @@ class ParallelScavengeHeap : public CollectedHeap {
static PSOldGen* _old_gen;
// Sizing policy for entire heap
- static PSAdaptiveSizePolicy* _size_policy;
- static PSGCAdaptivePolicyCounters* _gc_policy_counters;
+ static PSAdaptiveSizePolicy* _size_policy;
+ static PSGCAdaptivePolicyCounters* _gc_policy_counters;
static ParallelScavengeHeap* _psh;
@@ -67,7 +66,8 @@ class ParallelScavengeHeap : public CollectedHeap {
AdjoiningGenerations* _gens;
unsigned int _death_march_count;
- static GCTaskManager* _gc_task_manager; // The task manager.
+ // The task manager
+ static GCTaskManager* _gc_task_manager;
void trace_heap(GCWhen::Type when, GCTracer* tracer);
@@ -80,15 +80,14 @@ class ParallelScavengeHeap : public CollectedHeap {
HeapWord* mem_allocate_old_gen(size_t size);
public:
- ParallelScavengeHeap() : CollectedHeap() {
- _death_march_count = 0;
+ ParallelScavengeHeap() : CollectedHeap(), _death_march_count(0) {
set_alignment(_young_gen_alignment, intra_heap_alignment());
set_alignment(_old_gen_alignment, intra_heap_alignment());
}
// Return the (conservative) maximum heap alignment
static size_t conservative_max_heap_alignment() {
- return intra_heap_alignment();
+ return GenCollectorPolicy::intra_heap_alignment();
}
// For use by VM operations
@@ -103,8 +102,8 @@ class ParallelScavengeHeap : public CollectedHeap {
virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; }
- static PSYoungGen* young_gen() { return _young_gen; }
- static PSOldGen* old_gen() { return _old_gen; }
+ static PSYoungGen* young_gen() { return _young_gen; }
+ static PSOldGen* old_gen() { return _old_gen; }
virtual PSAdaptiveSizePolicy* size_policy() { return _size_policy; }
@@ -127,7 +126,7 @@ class ParallelScavengeHeap : public CollectedHeap {
// The alignment used for eden and survivors within the young gen
// and for boundary between young gen and old gen.
- static size_t intra_heap_alignment() { return 64 * K * HeapWordSize; }
+ size_t intra_heap_alignment() { return GenCollectorPolicy::intra_heap_alignment(); }
size_t capacity() const;
size_t used() const;
@@ -157,16 +156,15 @@ class ParallelScavengeHeap : public CollectedHeap {
virtual bool is_in_partial_collection(const void *p);
#endif
- bool is_in_young(oop p); // reserved part
- bool is_in_old(oop p); // reserved part
+ bool is_in_young(oop p); // reserved part
+ bool is_in_old(oop p); // reserved part
// Memory allocation. "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.
- HeapWord* mem_allocate(size_t size,
- bool* gc_overhead_limit_was_exceeded);
+ HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded);
// Allocation attempt(s) during a safepoint. It should never be called
// to allocate a new TLAB as this allocation might be satisfied out
@@ -257,7 +255,7 @@ class ParallelScavengeHeap : public CollectedHeap {
// Call these in sequential code around the processing of strong roots.
class ParStrongRootsScope : public MarkingCodeBlobClosure::MarkScope {
- public:
+ public:
ParStrongRootsScope();
~ParStrongRootsScope();
};
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp
index 8d411811b3c..1ffdf64e2aa 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp
@@ -46,8 +46,7 @@ PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
init_survivor_size,
gc_pause_goal_sec,
gc_cost_ratio),
- _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin/
- 100.0),
+ _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),
_intra_generation_alignment(intra_generation_alignment),
_live_at_last_full_gc(init_promo_size),
_gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp
index 585c7d06cab..8cd11de6ef2 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp
@@ -160,7 +160,7 @@ size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size) {
- const double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
+ const double max_gc_pause_sec = ((double) MaxGCPauseMillis) / 1000.0;
_size_policy = new AdaptiveSizePolicy(init_eden_size,
init_promo_size,
init_survivor_size,
@@ -192,6 +192,7 @@ void GenCollectorPolicy::initialize_flags() {
// make sure there room for eden and two survivor spaces
vm_exit_during_initialization("Too small new size specified");
}
+
if (SurvivorRatio < 1 || NewRatio < 1) {
vm_exit_during_initialization("Invalid young gen ratio specified");
}
@@ -465,7 +466,7 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
"generation sizes: using minimum heap = " SIZE_FORMAT,
_min_heap_byte_size);
}
- if ((OldSize > _max_gen1_size)) {
+ if (OldSize > _max_gen1_size) {
warning("Inconsistency between maximum heap size and maximum "
"generation sizes: using maximum heap = " SIZE_FORMAT
" -XX:OldSize flag is being ignored",
@@ -596,9 +597,7 @@ HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
gc_count_before = Universe::heap()->total_collections();
}
- VM_GenCollectForAllocation op(size,
- is_tlab,
- gc_count_before);
+ VM_GenCollectForAllocation op(size, is_tlab, gc_count_before);
VMThread::execute(&op);
if (op.prologue_succeeded()) {
result = op.result();
@@ -833,8 +832,9 @@ MarkSweepPolicy::MarkSweepPolicy() {
void MarkSweepPolicy::initialize_generations() {
_generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL);
- if (_generations == NULL)
+ if (_generations == NULL) {
vm_exit_during_initialization("Unable to allocate gen spec");
+ }
if (UseParNewGC) {
_generations[0] = new GenerationSpec(Generation::ParNew, _initial_gen0_size, _max_gen0_size);
@@ -843,8 +843,9 @@ void MarkSweepPolicy::initialize_generations() {
}
_generations[1] = new GenerationSpec(Generation::MarkSweepCompact, _initial_gen1_size, _max_gen1_size);
- if (_generations[0] == NULL || _generations[1] == NULL)
+ if (_generations[0] == NULL || _generations[1] == NULL) {
vm_exit_during_initialization("Unable to allocate gen spec");
+ }
}
void MarkSweepPolicy::initialize_gc_policy_counters() {
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp
index a86f45c54d7..bbfccdd644c 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.hpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp
@@ -79,6 +79,7 @@ class CollectorPolicy : public CHeapObj {
// Set to true when policy wants soft refs cleared.
// Reset to false by gc after it clears all soft refs.
bool _should_clear_all_soft_refs;
+
// Set to true by the GC if the just-completed gc cleared all
// softrefs. This is set to true whenever a gc clears all softrefs, and
// set to false each time gc returns to the mutator. For example, in the
@@ -101,8 +102,8 @@ class CollectorPolicy : public CHeapObj {
// Return maximum heap alignment that may be imposed by the policy
static size_t compute_max_alignment();
- size_t min_alignment() { return _min_alignment; }
- size_t max_alignment() { return _max_alignment; }
+ size_t min_alignment() { return _min_alignment; }
+ size_t max_alignment() { return _max_alignment; }
size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
size_t max_heap_byte_size() { return _max_heap_byte_size; }
@@ -248,7 +249,7 @@ class GenCollectorPolicy : public CollectorPolicy {
virtual int number_of_generations() = 0;
- virtual GenerationSpec **generations() {
+ virtual GenerationSpec **generations() {
assert(_generations != NULL, "Sanity check");
return _generations;
}
@@ -273,6 +274,12 @@ class GenCollectorPolicy : public CollectorPolicy {
virtual void initialize_size_policy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size);
+
+ // The alignment used for eden and survivors within the young gen
+ // and for boundary between young gen and old gen.
+ static size_t intra_heap_alignment() {
+ return 64 * K * HeapWordSize;
+ }
};
// All of hotspot's current collectors are subtypes of this
@@ -300,8 +307,8 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
// Inherited methods
TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }
- int number_of_generations() { return 2; }
- BarrierSet::Name barrier_set_name() { return BarrierSet::CardTableModRef; }
+ int number_of_generations() { return 2; }
+ BarrierSet::Name barrier_set_name() { return BarrierSet::CardTableModRef; }
virtual CollectorPolicy::Name kind() {
return CollectorPolicy::TwoGenerationCollectorPolicyKind;
diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp
index 3a5ab210c83..2b84542ef48 100644
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp
@@ -1053,12 +1053,6 @@ void GenCollectedHeap::save_marks() {
}
}
-void GenCollectedHeap::compute_new_generation_sizes(int collectedGen) {
- for (int i = 0; i <= collectedGen; i++) {
- _gens[i]->compute_new_size();
- }
-}
-
GenCollectedHeap* GenCollectedHeap::heap() {
assert(_gch != NULL, "Uninitialized access to GenCollectedHeap::heap()");
assert(_gch->kind() == CollectedHeap::GenCollectedHeap, "not a generational heap");
diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp
index 8f814132a78..5cd8a71280a 100644
--- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp
@@ -86,10 +86,6 @@ public:
NOT_PRODUCT(static size_t _skip_header_HeapWords;)
protected:
- // Directs each generation up to and including "collectedGen" to recompute
- // its desired size.
- void compute_new_generation_sizes(int collectedGen);
-
// Helper functions for allocation
HeapWord* attempt_allocation(size_t size,
bool is_tlab,
diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp
index 1f632ae478f..18c9733076c 100644
--- a/hotspot/src/share/vm/memory/universe.cpp
+++ b/hotspot/src/share/vm/memory/universe.cpp
@@ -1021,7 +1021,7 @@ bool universe_post_init() {
Universe::_virtual_machine_error_instance =
InstanceKlass::cast(k)->allocate_instance(CHECK_false);
- Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
+ Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
if (!DumpSharedSpaces) {
// These are the only Java fields that are currently set during shared space dumping.
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 8060dae0377..1e82e5bdca8 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -1408,7 +1408,7 @@ uintx Arguments::max_heap_for_compressed_oops() {
// NULL page is located before the heap, we pad the NULL page to the conservative
// maximum alignment that the GC may ever impose upon the heap.
size_t displacement_due_to_null_page = align_size_up_(os::vm_page_size(),
- Arguments::conservative_max_heap_alignment());
+ _conservative_max_heap_alignment);
LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page);
NOT_LP64(ShouldNotReachHere(); return 0);
@@ -2681,9 +2681,10 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
describe_range_error(errcode);
return JNI_EINVAL;
}
- FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size);
+ set_min_heap_size((uintx)long_initial_heap_size);
// Currently the minimum size and the initial heap sizes are the same.
- set_min_heap_size(InitialHeapSize);
+ // Can be overridden with -XX:InitialHeapSize.
+ FLAG_SET_CMDLINE(uintx, InitialHeapSize, (uintx)long_initial_heap_size);
// -Xmx
} else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
julong long_max_heap_size = 0;
From 8fe7a15c08336c8428c4470605da77c2fa4bff43 Mon Sep 17 00:00:00 2001
From: Staffan Larsen
Date: Fri, 1 Nov 2013 10:08:10 +0100
Subject: [PATCH 005/110] 8027692: Remove
java/lang/management/MemoryMXBean/LowMemoryTest2.sh from ProblemList.txt
Reviewed-by: stefank, alanb
---
jdk/test/ProblemList.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index ea99549a0f7..202f703b713 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -128,9 +128,6 @@ java/lang/management/ThreadMXBean/ThreadStateTest.java generic-all
# 7067973
java/lang/management/MemoryMXBean/CollectionUsageThreshold.java generic-all
-# 7196801
-java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all
-
# 8021230
java/lang/ThreadLocal/ThreadLocalSupplierTest.java generic-all
From fdbeb8e0fb4a958fb8a95e70466e51a7acfc7375 Mon Sep 17 00:00:00 2001
From: Staffan Larsen
Date: Fri, 1 Nov 2013 15:10:10 +0100
Subject: [PATCH 006/110] 8027705: com/sun/jdi/JdbMethodExitTest.sh fails when
a background thread is generating events
Reviewed-by: dcubed
---
jdk/test/com/sun/jdi/JdbMethodExitTest.sh | 20 +++++----
jdk/test/com/sun/jdi/ShellScaffold.sh | 52 +++++++++++++++++++++++
2 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/jdk/test/com/sun/jdi/JdbMethodExitTest.sh b/jdk/test/com/sun/jdi/JdbMethodExitTest.sh
index 52c0fe7becf..ab00816ca6e 100644
--- a/jdk/test/com/sun/jdi/JdbMethodExitTest.sh
+++ b/jdk/test/com/sun/jdi/JdbMethodExitTest.sh
@@ -156,7 +156,7 @@ class $classname {
// a resume.
$classname xx = new $classname();
-
+ System.out.println("threadid="+Thread.currentThread().getId());
bkpt();
// test all possible return types
@@ -197,6 +197,8 @@ dojdbCmds()
# test all possible return types
runToBkpt @1
+ debuggeeMatchRegexp "s/threadid=\(.*\)/\1/g"
+ threadid=$?
cmd untrace
cmd trace methods
@@ -226,7 +228,7 @@ dojdbCmds()
# trace exit of methods with all the return values
# (but just check a couple of them)
- cmd trace go exits
+ cmd trace go method exits $threadid
cmd cont
jdbFailIfNotPresent "instance of JdbMethodExitTest"
jdbFailIfNotPresent "return value = 8"
@@ -235,7 +237,7 @@ dojdbCmds()
cmd step up
- cmd trace methods
+ cmd trace methods $threadid
cmd cont
jdbFailIfNotPresent "Method entered:"
cmd cont
@@ -243,7 +245,9 @@ dojdbCmds()
cmd step up
- cmd trace go methods
+ cmd trace go methods $threadid
+ cmd cont
+ cmd cont
cmd cont
jdbFailIfNotPresent "Method entered: \"thread=main\", JdbMethodExitTest.traceMethods1"
jdbFailIfNotPresent 'Method exited: .* JdbMethodExitTest.traceMethods1'
@@ -251,14 +255,14 @@ dojdbCmds()
cmd step up
- cmd trace method exits
+ cmd trace method exits $threadid
cmd cont
jdbFailIfNotPresent "Method exited: return value = \"traceExits\""
cmd untrace
cmd step up
- cmd trace go method exits
+ cmd trace go method exits $threadid
cmd cont
jdbFailIfNotPresent 'Method exited: .* JdbMethodExitTest.traceExits1'
cmd untrace
@@ -266,7 +270,7 @@ dojdbCmds()
cmd step # step into traceExit()
- cmd trace method exit
+ cmd trace method exit $threadid
cmd cont
jdbFailIfNotPresent "Method exited: return value = \"traceExit\""
cmd untrace
@@ -275,7 +279,7 @@ dojdbCmds()
cmd step
cmd step # skip over setting return value in caller :-(
- cmd trace go method exit
+ cmd trace go method exit $threadid
cmd cont
jdbFailIfNotPresent 'Method exited: .*JdbMethodExitTest.traceExit1'
cmd quit
diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh
index d8635e3dda9..6ed55c1ae91 100644
--- a/jdk/test/com/sun/jdi/ShellScaffold.sh
+++ b/jdk/test/com/sun/jdi/ShellScaffold.sh
@@ -1004,6 +1004,50 @@ grepForString()
return $stat
}
+# $1 is the filename, $2 is the regexp to match and return,
+# $3 is the number of lines to search (from the end)
+matchRegexp()
+{
+ if [ -z "$3" ] ; then
+ theCmd=cat
+ else
+ theCmd="tail -$3"
+ fi
+
+ case "$2" in
+ *\>*)
+ # Target string contains a '>' so we better not ignore it
+ res=`$theCmd $1 | sed -e "$2"`
+ ;;
+ *)
+ # Target string does not contain a '>'.
+ # NOTE: if $1 does not end with a new line, piping it to sed
+ # doesn't include the chars on the last line. Detect this
+ # case, and add a new line.
+ theFile="$1"
+ if [ `tail -1 "$theFile" | wc -l | sed -e 's@ @@g'` = 0 ] ; then
+ # The target file doesn't end with a new line so we have
+ # add one to a copy of the target file so the sed command
+ # below can filter that last line.
+ cp "$theFile" "$theFile.tmp"
+ theFile="$theFile.tmp"
+ echo >> "$theFile"
+ fi
+
+ # See bug 6220903. Sometimes the jdb prompt chars ('> ') can
+ # get interleaved in the target file which can keep us from
+ # matching the target string.
+ res=`$theCmd "$theFile" | sed -e 's@> @@g' -e 's@>@@g' \
+ | sed -e "$2"`
+ if [ "$theFile" != "$1" ]; then
+ # remove the copy of the target file
+ rm -f "$theFile"
+ fi
+ unset theFile
+ esac
+ return $res
+}
+
# $1 is the filename, $2 is the string to look for,
# $3 is the number of lines to search (from the end)
failIfPresent()
@@ -1058,6 +1102,14 @@ debuggeeFailIfPresent()
failIfPresent $debuggeeOutFile "$1" $2
}
+# match and return the output from the regexp $1 in the debuggee output
+# $2 is the number of lines to search (from the end)
+debuggeeMatchRegexp()
+{
+ matchRegexp $debuggeeOutFile "$1" $2
+}
+
+
# This should really be named 'done' instead of pass.
pass()
{
From 0fa3a71c8a4821327ebada5673596889f8df8a7d Mon Sep 17 00:00:00 2001
From: Jesper Wilhelmsson
Date: Fri, 1 Nov 2013 17:09:38 +0100
Subject: [PATCH 007/110] 8016309: assert(eden_size > 0 && survivor_size > 0)
failed: just checking 7057939: jmap shows MaxNewSize=4GB when Java is using
parallel collector
Major cleanup of the collectorpolicy classes
Reviewed-by: tschatzl, jcoomes
---
.../cmsCollectorPolicy.cpp | 5 +-
.../cmsCollectorPolicy.hpp | 3 +-
.../gc_implementation/g1/g1CollectedHeap.cpp | 2 +-
.../g1/g1CollectorPolicy.cpp | 76 +++-
.../g1/g1CollectorPolicy.hpp | 15 +-
.../vm/gc_implementation/g1/heapRegion.cpp | 5 -
.../parallelScavenge/adjoiningGenerations.cpp | 19 +-
.../parallelScavenge/adjoiningGenerations.hpp | 10 +-
.../parallelScavenge/asPSOldGen.cpp | 4 +-
.../parallelScavenge/asPSYoungGen.cpp | 10 +-
.../parallelScavenge/generationSizer.cpp | 84 ++++
.../parallelScavenge/generationSizer.hpp | 40 +-
.../parallelScavenge/parallelScavengeHeap.cpp | 85 +---
.../parallelScavenge/parallelScavengeHeap.hpp | 40 +-
.../parallelScavenge/psAdaptiveSizePolicy.cpp | 46 +-
.../parallelScavenge/psAdaptiveSizePolicy.hpp | 6 +-
.../parallelScavenge/psYoungGen.cpp | 13 +-
.../share/vm/gc_interface/collectedHeap.cpp | 4 +
.../src/share/vm/memory/collectorPolicy.cpp | 422 ++++++++++++------
.../src/share/vm/memory/collectorPolicy.hpp | 83 ++--
.../src/share/vm/memory/defNewGeneration.cpp | 6 +-
.../src/share/vm/memory/genCollectedHeap.cpp | 2 +-
hotspot/src/share/vm/memory/sharedHeap.cpp | 1 +
hotspot/src/share/vm/memory/universe.cpp | 2 +
hotspot/src/share/vm/prims/whitebox.cpp | 2 +-
hotspot/src/share/vm/runtime/arguments.cpp | 6 +-
.../gc/arguments/TestMaxHeapSizeTools.java | 33 +-
hotspot/test/gc/arguments/TestMaxNewSize.java | 122 +++++
28 files changed, 718 insertions(+), 428 deletions(-)
create mode 100644 hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp
create mode 100644 hotspot/test/gc/arguments/TestMaxNewSize.java
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
index c2aafb7bc20..a236a10efb3 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
@@ -47,8 +47,9 @@
// ConcurrentMarkSweepPolicy methods
//
-ConcurrentMarkSweepPolicy::ConcurrentMarkSweepPolicy() {
- initialize_all();
+void ConcurrentMarkSweepPolicy::initialize_alignments() {
+ _space_alignment = _gen_alignment = (uintx)Generation::GenGrain;
+ _heap_alignment = compute_heap_alignment();
}
void ConcurrentMarkSweepPolicy::initialize_generations() {
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp
index 1483bca13eb..d26959f3d9f 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp
@@ -29,10 +29,11 @@
class ConcurrentMarkSweepPolicy : public TwoGenerationCollectorPolicy {
protected:
+ void initialize_alignments();
void initialize_generations();
public:
- ConcurrentMarkSweepPolicy();
+ ConcurrentMarkSweepPolicy() {}
ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return this; }
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index 3f53067ca8d..85709465b3e 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -2008,7 +2008,7 @@ jint G1CollectedHeap::initialize() {
size_t init_byte_size = collector_policy()->initial_heap_byte_size();
size_t max_byte_size = collector_policy()->max_heap_byte_size();
- size_t heap_alignment = collector_policy()->max_alignment();
+ size_t heap_alignment = collector_policy()->heap_alignment();
// Ensure that the sizes are properly aligned.
Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index ad1dce1750b..b4f9a0b0007 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -313,27 +313,38 @@ G1CollectorPolicy::G1CollectorPolicy() :
// for the first time during initialization.
_reserve_regions = 0;
- initialize_all();
_collectionSetChooser = new CollectionSetChooser();
- _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
+}
+
+void G1CollectorPolicy::initialize_alignments() {
+ _space_alignment = HeapRegion::GrainBytes;
+ size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
+ size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+ _heap_alignment = MAX3(card_table_alignment, _space_alignment, page_size);
}
void G1CollectorPolicy::initialize_flags() {
- _min_alignment = HeapRegion::GrainBytes;
- size_t card_table_alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
- size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
- _max_alignment = MAX3(card_table_alignment, _min_alignment, page_size);
+ if (G1HeapRegionSize != HeapRegion::GrainBytes) {
+ FLAG_SET_ERGO(uintx, G1HeapRegionSize, HeapRegion::GrainBytes);
+ }
+
if (SurvivorRatio < 1) {
vm_exit_during_initialization("Invalid survivor ratio specified");
}
CollectorPolicy::initialize_flags();
+ _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
}
-G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) {
- assert(G1NewSizePercent <= G1MaxNewSizePercent, "Min larger than max");
- assert(G1NewSizePercent > 0 && G1NewSizePercent < 100, "Min out of bounds");
- assert(G1MaxNewSizePercent > 0 && G1MaxNewSizePercent < 100, "Max out of bounds");
+void G1CollectorPolicy::post_heap_initialize() {
+ uintx max_regions = G1CollectedHeap::heap()->max_regions();
+ size_t max_young_size = (size_t)_young_gen_sizer->max_young_length(max_regions) * HeapRegion::GrainBytes;
+ if (max_young_size != MaxNewSize) {
+ FLAG_SET_ERGO(uintx, MaxNewSize, max_young_size);
+ }
+}
+G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
+ _min_desired_young_length(0), _max_desired_young_length(0) {
if (FLAG_IS_CMDLINE(NewRatio)) {
if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
@@ -344,8 +355,13 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(
}
}
- if (FLAG_IS_CMDLINE(NewSize) && FLAG_IS_CMDLINE(MaxNewSize) && NewSize > MaxNewSize) {
- vm_exit_during_initialization("Initial young gen size set larger than the maximum young gen size");
+ if (NewSize > MaxNewSize) {
+ if (FLAG_IS_CMDLINE(MaxNewSize)) {
+ warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
+ "A new max generation size of " SIZE_FORMAT "k will be used.",
+ NewSize/K, MaxNewSize/K, NewSize/K);
+ }
+ MaxNewSize = NewSize;
}
if (FLAG_IS_CMDLINE(NewSize)) {
@@ -378,34 +394,48 @@ uint G1YoungGenSizer::calculate_default_max_length(uint new_number_of_heap_regio
return MAX2(1U, default_value);
}
-void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
- assert(new_number_of_heap_regions > 0, "Heap must be initialized");
+void G1YoungGenSizer::recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length) {
+ assert(number_of_heap_regions > 0, "Heap must be initialized");
switch (_sizer_kind) {
case SizerDefaults:
- _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions);
- _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions);
+ *min_young_length = calculate_default_min_length(number_of_heap_regions);
+ *max_young_length = calculate_default_max_length(number_of_heap_regions);
break;
case SizerNewSizeOnly:
- _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions);
- _max_desired_young_length = MAX2(_min_desired_young_length, _max_desired_young_length);
+ *max_young_length = calculate_default_max_length(number_of_heap_regions);
+ *max_young_length = MAX2(*min_young_length, *max_young_length);
break;
case SizerMaxNewSizeOnly:
- _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions);
- _min_desired_young_length = MIN2(_min_desired_young_length, _max_desired_young_length);
+ *min_young_length = calculate_default_min_length(number_of_heap_regions);
+ *min_young_length = MIN2(*min_young_length, *max_young_length);
break;
case SizerMaxAndNewSize:
// Do nothing. Values set on the command line, don't update them at runtime.
break;
case SizerNewRatio:
- _min_desired_young_length = new_number_of_heap_regions / (NewRatio + 1);
- _max_desired_young_length = _min_desired_young_length;
+ *min_young_length = number_of_heap_regions / (NewRatio + 1);
+ *max_young_length = *min_young_length;
break;
default:
ShouldNotReachHere();
}
- assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
+ assert(*min_young_length <= *max_young_length, "Invalid min/max young gen size values");
+}
+
+uint G1YoungGenSizer::max_young_length(uint number_of_heap_regions) {
+ // We need to pass the desired values because recalculation may not update these
+ // values in some cases.
+ uint temp = _min_desired_young_length;
+ uint result = _max_desired_young_length;
+ recalculate_min_max_young_length(number_of_heap_regions, &temp, &result);
+ return result;
+}
+
+void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
+ recalculate_min_max_young_length(new_number_of_heap_regions, &_min_desired_young_length,
+ &_max_desired_young_length);
}
void G1CollectorPolicy::init() {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
index 037876e07e7..438bec82c51 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
@@ -136,8 +136,16 @@ private:
uint calculate_default_min_length(uint new_number_of_heap_regions);
uint calculate_default_max_length(uint new_number_of_heap_regions);
+ // Update the given values for minimum and maximum young gen length in regions
+ // given the number of heap regions depending on the kind of sizing algorithm.
+ void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
+
public:
G1YoungGenSizer();
+ // Calculate the maximum length of the young gen given the number of regions
+ // depending on the sizing algorithm.
+ uint max_young_length(uint number_of_heap_regions);
+
void heap_size_changed(uint new_number_of_heap_regions);
uint min_desired_young_length() {
return _min_desired_young_length;
@@ -165,13 +173,9 @@ private:
G1MMUTracker* _mmu_tracker;
+ void initialize_alignments();
void initialize_flags();
- void initialize_all() {
- initialize_flags();
- initialize_size_info();
- }
-
CollectionSetChooser* _collectionSetChooser;
double _full_collection_start_sec;
@@ -931,6 +935,7 @@ public:
// Calculates survivor space parameters.
void update_survivors_policy();
+ virtual void post_heap_initialize();
};
// This should move to some place more general...
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
index 00eec548995..e4f534ab5a2 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
@@ -174,11 +174,6 @@ void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_hea
region_size = MAX_REGION_SIZE;
}
- if (region_size != G1HeapRegionSize) {
- // Update the flag to make sure that PrintFlagsFinal logs the correct value
- FLAG_SET_ERGO(uintx, G1HeapRegionSize, region_size);
- }
-
// And recalculate the log.
region_size_log = log2_long((jlong) region_size);
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp
index 996a522927b..90bf630fe36 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc_implementation/parallelScavenge/adjoiningGenerations.hpp"
#include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
// If boundary moving is being used, create the young gen and old
@@ -32,15 +33,17 @@
// the old behavior otherwise (with PSYoungGen and PSOldGen).
AdjoiningGenerations::AdjoiningGenerations(ReservedSpace old_young_rs,
- size_t init_low_byte_size,
- size_t min_low_byte_size,
- size_t max_low_byte_size,
- size_t init_high_byte_size,
- size_t min_high_byte_size,
- size_t max_high_byte_size,
+ GenerationSizer* policy,
size_t alignment) :
- _virtual_spaces(old_young_rs, min_low_byte_size,
- min_high_byte_size, alignment) {
+ _virtual_spaces(old_young_rs, policy->min_gen1_size(),
+ policy->min_gen0_size(), alignment) {
+ size_t init_low_byte_size = policy->initial_gen1_size();
+ size_t min_low_byte_size = policy->min_gen1_size();
+ size_t max_low_byte_size = policy->max_gen1_size();
+ size_t init_high_byte_size = policy->initial_gen0_size();
+ size_t min_high_byte_size = policy->min_gen0_size();
+ size_t max_high_byte_size = policy->max_gen0_size();
+
assert(min_low_byte_size <= init_low_byte_size &&
init_low_byte_size <= max_low_byte_size, "Parameter check");
assert(min_high_byte_size <= init_high_byte_size &&
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp
index 70afb9996ae..950baa1d53f 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp
@@ -28,6 +28,7 @@
#include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
#include "gc_implementation/parallelScavenge/asPSOldGen.hpp"
#include "gc_implementation/parallelScavenge/asPSYoungGen.hpp"
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
// Contains two generations that both use an AdjoiningVirtualSpaces.
@@ -56,14 +57,7 @@ class AdjoiningGenerations : public CHeapObj {
bool request_young_gen_expansion(size_t desired_change_in_bytes);
public:
- AdjoiningGenerations(ReservedSpace rs,
- size_t init_low_byte_size,
- size_t min_low_byte_size,
- size_t max_low_byte_size,
- size_t init_high_byte_size,
- size_t min_high_byte_size,
- size_t max_high_bytes_size,
- size_t alignment);
+ AdjoiningGenerations(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
// Accessors
PSYoungGen* young_gen() { return _young_gen; }
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp
index 6f7026e5a0c..9d2e8182e06 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSOldGen.cpp
@@ -91,7 +91,7 @@ size_t ASPSOldGen::available_for_expansion() {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
size_t result = gen_size_limit() - virtual_space()->committed_size();
- size_t result_aligned = align_size_down(result, heap->old_gen_alignment());
+ size_t result_aligned = align_size_down(result, heap->generation_alignment());
return result_aligned;
}
@@ -102,7 +102,7 @@ size_t ASPSOldGen::available_for_contraction() {
}
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t gen_alignment = heap->old_gen_alignment();
+ const size_t gen_alignment = heap->generation_alignment();
PSAdaptiveSizePolicy* policy = heap->size_policy();
const size_t working_size =
used_in_bytes() + (size_t) policy->avg_promoted()->padded_average();
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
index a7b2eb28ef2..105772487c0 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp
@@ -75,7 +75,7 @@ size_t ASPSYoungGen::available_for_expansion() {
"generation size limit is wrong");
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
size_t result = gen_size_limit() - current_committed_size;
- size_t result_aligned = align_size_down(result, heap->young_gen_alignment());
+ size_t result_aligned = align_size_down(result, heap->generation_alignment());
return result_aligned;
}
@@ -92,8 +92,8 @@ size_t ASPSYoungGen::available_for_contraction() {
if (eden_space()->is_empty()) {
// Respect the minimum size for eden and for the young gen as a whole.
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t eden_alignment = heap->intra_heap_alignment();
- const size_t gen_alignment = heap->young_gen_alignment();
+ const size_t eden_alignment = heap->space_alignment();
+ const size_t gen_alignment = heap->generation_alignment();
assert(eden_space()->capacity_in_bytes() >= eden_alignment,
"Alignment is wrong");
@@ -129,7 +129,7 @@ size_t ASPSYoungGen::available_for_contraction() {
// to_space can be.
size_t ASPSYoungGen::available_to_live() {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t alignment = heap->intra_heap_alignment();
+ const size_t alignment = heap->space_alignment();
// Include any space that is committed but is not in eden.
size_t available = pointer_delta(eden_space()->bottom(),
@@ -293,7 +293,7 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size,
assert(eden_start < from_start, "Cannot push into from_space");
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t alignment = heap->intra_heap_alignment();
+ const size_t alignment = heap->space_alignment();
const bool maintain_minimum =
(requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp
new file mode 100644
index 00000000000..638460524eb
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001, 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.
+ *
+ * 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_implementation/parallelScavenge/generationSizer.hpp"
+#include "memory/collectorPolicy.hpp"
+
+void GenerationSizer::trace_gen_sizes(const char* const str) {
+ if (TracePageSizes) {
+ tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " "
+ SIZE_FORMAT "," SIZE_FORMAT " "
+ SIZE_FORMAT,
+ str,
+ _min_gen1_size / K, _max_gen1_size / K,
+ _min_gen0_size / K, _max_gen0_size / K,
+ _max_heap_byte_size / K);
+ }
+}
+
+void GenerationSizer::initialize_alignments() {
+ _space_alignment = _gen_alignment = default_gen_alignment();
+ _heap_alignment = compute_heap_alignment();
+}
+
+void GenerationSizer::initialize_flags() {
+ // Do basic sizing work
+ TwoGenerationCollectorPolicy::initialize_flags();
+
+ assert(UseSerialGC ||
+ !FLAG_IS_DEFAULT(ParallelGCThreads) ||
+ (ParallelGCThreads > 0),
+ "ParallelGCThreads should be set before flag initialization");
+
+ // The survivor ratio's are calculated "raw", unlike the
+ // default gc, which adds 2 to the ratio value. We need to
+ // make sure the values are valid before using them.
+ if (MinSurvivorRatio < 3) {
+ FLAG_SET_ERGO(uintx, MinSurvivorRatio, 3);
+ }
+
+ if (InitialSurvivorRatio < 3) {
+ FLAG_SET_ERGO(uintx, InitialSurvivorRatio, 3);
+ }
+}
+
+void GenerationSizer::initialize_size_info() {
+ trace_gen_sizes("ps heap raw");
+ const size_t page_sz = os::page_size_for_region(_min_heap_byte_size,
+ _max_heap_byte_size,
+ 8);
+
+ // Can a page size be something else than a power of two?
+ assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
+ size_t new_alignment = round_to(page_sz, _gen_alignment);
+ if (new_alignment != _gen_alignment) {
+ _gen_alignment = new_alignment;
+ // Redo everything from the start
+ initialize_flags();
+ }
+ TwoGenerationCollectorPolicy::initialize_size_info();
+
+ trace_gen_sizes("ps heap rnd");
+}
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp
index f7be7671ff9..eb8c78a8c81 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp
@@ -31,41 +31,17 @@
// TwoGenerationCollectorPolicy. Lets reuse it!
class GenerationSizer : public TwoGenerationCollectorPolicy {
- public:
- GenerationSizer() {
- // Partial init only!
- initialize_flags();
- initialize_size_info();
- }
+ private:
- void initialize_flags() {
- // Do basic sizing work
- TwoGenerationCollectorPolicy::initialize_flags();
+ void trace_gen_sizes(const char* const str);
- assert(UseSerialGC ||
- !FLAG_IS_DEFAULT(ParallelGCThreads) ||
- (ParallelGCThreads > 0),
- "ParallelGCThreads should be set before flag initialization");
+ // The alignment used for boundary between young gen and old gen
+ static size_t default_gen_alignment() { return 64 * K * HeapWordSize; }
- // The survivor ratio's are calculated "raw", unlike the
- // default gc, which adds 2 to the ratio value. We need to
- // make sure the values are valid before using them.
- if (MinSurvivorRatio < 3) {
- MinSurvivorRatio = 3;
- }
+ protected:
- if (InitialSurvivorRatio < 3) {
- InitialSurvivorRatio = 3;
- }
- }
-
- size_t min_young_gen_size() { return _min_gen0_size; }
- size_t young_gen_size() { return _initial_gen0_size; }
- size_t max_young_gen_size() { return _max_gen0_size; }
-
- size_t min_old_gen_size() { return _min_gen1_size; }
- size_t old_gen_size() { return _initial_gen1_size; }
- size_t max_old_gen_size() { return _max_gen1_size; }
+ void initialize_alignments();
+ void initialize_flags();
+ void initialize_size_info();
};
-
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GENERATIONSIZER_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
index e5d5229d30c..f93f2e8991f 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
@@ -52,76 +52,20 @@ PSGCAdaptivePolicyCounters* ParallelScavengeHeap::_gc_policy_counters = NULL;
ParallelScavengeHeap* ParallelScavengeHeap::_psh = NULL;
GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
-static void trace_gen_sizes(const char* const str,
- size_t og_min, size_t og_max,
- size_t yg_min, size_t yg_max)
-{
- if (TracePageSizes) {
- tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " "
- SIZE_FORMAT "," SIZE_FORMAT " "
- SIZE_FORMAT,
- str,
- og_min / K, og_max / K,
- yg_min / K, yg_max / K,
- (og_max + yg_max) / K);
- }
-}
-
jint ParallelScavengeHeap::initialize() {
CollectedHeap::pre_initialize();
- // Cannot be initialized until after the flags are parsed
- // GenerationSizer flag_parser;
+ // Initialize collector policy
_collector_policy = new GenerationSizer();
+ _collector_policy->initialize_all();
- size_t yg_min_size = _collector_policy->min_young_gen_size();
- size_t yg_max_size = _collector_policy->max_young_gen_size();
- size_t og_min_size = _collector_policy->min_old_gen_size();
- size_t og_max_size = _collector_policy->max_old_gen_size();
-
- trace_gen_sizes("ps heap raw",
- og_min_size, og_max_size,
- yg_min_size, yg_max_size);
-
- const size_t og_page_sz = os::page_size_for_region(yg_min_size + og_min_size,
- yg_max_size + og_max_size,
- 8);
-
- const size_t og_align = set_alignment(_old_gen_alignment, og_page_sz);
- const size_t yg_align = set_alignment(_young_gen_alignment, og_page_sz);
-
- // Update sizes to reflect the selected page size(s).
- //
- // NEEDS_CLEANUP. The default TwoGenerationCollectorPolicy uses NewRatio; it
- // should check UseAdaptiveSizePolicy. Changes from generationSizer could
- // move to the common code.
- yg_min_size = align_size_up(yg_min_size, yg_align);
- yg_max_size = align_size_up(yg_max_size, yg_align);
- size_t yg_cur_size =
- align_size_up(_collector_policy->young_gen_size(), yg_align);
- yg_cur_size = MAX2(yg_cur_size, yg_min_size);
-
- og_min_size = align_size_up(og_min_size, og_align);
- // Align old gen size down to preserve specified heap size.
- assert(og_align == yg_align, "sanity");
- og_max_size = align_size_down(og_max_size, og_align);
- og_max_size = MAX2(og_max_size, og_min_size);
- size_t og_cur_size =
- align_size_down(_collector_policy->old_gen_size(), og_align);
- og_cur_size = MAX2(og_cur_size, og_min_size);
-
- trace_gen_sizes("ps heap rnd",
- og_min_size, og_max_size,
- yg_min_size, yg_max_size);
-
- const size_t heap_size = og_max_size + yg_max_size;
-
- ReservedSpace heap_rs = Universe::reserve_heap(heap_size, og_align);
+ const size_t heap_size = _collector_policy->max_heap_byte_size();
+ ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment());
MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtJavaHeap);
- os::trace_page_sizes("ps main", og_min_size + yg_min_size,
- og_max_size + yg_max_size, og_page_sz,
+ os::trace_page_sizes("ps main", _collector_policy->min_heap_byte_size(),
+ heap_size, generation_alignment(),
heap_rs.base(),
heap_rs.size());
if (!heap_rs.is_reserved()) {
@@ -142,12 +86,6 @@ jint ParallelScavengeHeap::initialize() {
return JNI_ENOMEM;
}
- // Initial young gen size is 4 Mb
- //
- // XXX - what about flag_parser.young_gen_size()?
- const size_t init_young_size = align_size_up(4 * M, yg_align);
- yg_cur_size = MAX2(MIN2(init_young_size, yg_max_size), yg_cur_size);
-
// Make up the generations
// Calculate the maximum size that a generation can grow. This
// includes growth into the other generation. Note that the
@@ -157,14 +95,7 @@ jint ParallelScavengeHeap::initialize() {
double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
- _gens = new AdjoiningGenerations(heap_rs,
- og_cur_size,
- og_min_size,
- og_max_size,
- yg_cur_size,
- yg_min_size,
- yg_max_size,
- yg_align);
+ _gens = new AdjoiningGenerations(heap_rs, _collector_policy, generation_alignment());
_old_gen = _gens->old_gen();
_young_gen = _gens->young_gen();
@@ -176,7 +107,7 @@ jint ParallelScavengeHeap::initialize() {
new PSAdaptiveSizePolicy(eden_capacity,
initial_promo_size,
young_gen()->to_space()->capacity_in_bytes(),
- intra_heap_alignment(),
+ _collector_policy->gen_alignment(),
max_gc_pause_sec,
max_gc_minor_pause_sec,
GCTimeRatio
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
index 2ef42c86660..51f40d8c62b 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP
+#include "gc_implementation/parallelScavenge/generationSizer.hpp"
#include "gc_implementation/parallelScavenge/objectStartArray.hpp"
#include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp"
#include "gc_implementation/parallelScavenge/psOldGen.hpp"
@@ -32,13 +33,12 @@
#include "gc_implementation/shared/gcPolicyCounters.hpp"
#include "gc_implementation/shared/gcWhen.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
+#include "memory/collectorPolicy.hpp"
#include "utilities/ostream.hpp"
class AdjoiningGenerations;
class GCHeapSummary;
class GCTaskManager;
-class GenerationSizer;
-class CollectorPolicy;
class PSAdaptiveSizePolicy;
class PSHeapSummary;
@@ -54,13 +54,8 @@ class ParallelScavengeHeap : public CollectedHeap {
static ParallelScavengeHeap* _psh;
- size_t _young_gen_alignment;
- size_t _old_gen_alignment;
-
GenerationSizer* _collector_policy;
- inline size_t set_alignment(size_t& var, size_t val);
-
// Collection of generations that are adjacent in the
// space reserved for the heap.
AdjoiningGenerations* _gens;
@@ -80,15 +75,7 @@ class ParallelScavengeHeap : public CollectedHeap {
HeapWord* mem_allocate_old_gen(size_t size);
public:
- ParallelScavengeHeap() : CollectedHeap(), _death_march_count(0) {
- set_alignment(_young_gen_alignment, intra_heap_alignment());
- set_alignment(_old_gen_alignment, intra_heap_alignment());
- }
-
- // Return the (conservative) maximum heap alignment
- static size_t conservative_max_heap_alignment() {
- return GenCollectorPolicy::intra_heap_alignment();
- }
+ ParallelScavengeHeap() : CollectedHeap(), _death_march_count(0) { }
// For use by VM operations
enum CollectionType {
@@ -120,13 +107,15 @@ class ParallelScavengeHeap : public CollectedHeap {
void post_initialize();
void update_counters();
- // The alignment used for the various generations.
- size_t young_gen_alignment() const { return _young_gen_alignment; }
- size_t old_gen_alignment() const { return _old_gen_alignment; }
- // The alignment used for eden and survivors within the young gen
- // and for boundary between young gen and old gen.
- size_t intra_heap_alignment() { return GenCollectorPolicy::intra_heap_alignment(); }
+ // The alignment used for the various areas
+ size_t space_alignment() { return _collector_policy->space_alignment(); }
+ size_t generation_alignment() { return _collector_policy->gen_alignment(); }
+
+ // Return the (conservative) maximum heap alignment
+ static size_t conservative_max_heap_alignment() {
+ return CollectorPolicy::compute_heap_alignment();
+ }
size_t capacity() const;
size_t used() const;
@@ -261,11 +250,4 @@ class ParallelScavengeHeap : public CollectedHeap {
};
};
-inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
-{
- assert(is_power_of_2((intptr_t)val), "must be a power of 2");
- var = round_to(val, intra_heap_alignment());
- return var;
-}
-
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARALLELSCAVENGEHEAP_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp
index 1ffdf64e2aa..a2f2fa722bf 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp
@@ -37,7 +37,7 @@
PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size,
- size_t intra_generation_alignment,
+ size_t space_alignment,
double gc_pause_goal_sec,
double gc_minor_pause_goal_sec,
uint gc_cost_ratio) :
@@ -47,7 +47,7 @@ PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
gc_pause_goal_sec,
gc_cost_ratio),
_collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),
- _intra_generation_alignment(intra_generation_alignment),
+ _space_alignment(space_alignment),
_live_at_last_full_gc(init_promo_size),
_gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
_latest_major_mutator_interval_seconds(0),
@@ -352,11 +352,10 @@ void PSAdaptiveSizePolicy::compute_eden_space_size(
}
// Align everything and make a final limit check
- const size_t alignment = _intra_generation_alignment;
- desired_eden_size = align_size_up(desired_eden_size, alignment);
- desired_eden_size = MAX2(desired_eden_size, alignment);
+ desired_eden_size = align_size_up(desired_eden_size, _space_alignment);
+ desired_eden_size = MAX2(desired_eden_size, _space_alignment);
- eden_limit = align_size_down(eden_limit, alignment);
+ eden_limit = align_size_down(eden_limit, _space_alignment);
// And one last limit check, now that we've aligned things.
if (desired_eden_size > eden_limit) {
@@ -560,11 +559,10 @@ void PSAdaptiveSizePolicy::compute_old_gen_free_space(
}
// Align everything and make a final limit check
- const size_t alignment = _intra_generation_alignment;
- desired_promo_size = align_size_up(desired_promo_size, alignment);
- desired_promo_size = MAX2(desired_promo_size, alignment);
+ desired_promo_size = align_size_up(desired_promo_size, _space_alignment);
+ desired_promo_size = MAX2(desired_promo_size, _space_alignment);
- promo_limit = align_size_down(promo_limit, alignment);
+ promo_limit = align_size_down(promo_limit, _space_alignment);
// And one last limit check, now that we've aligned things.
desired_promo_size = MIN2(desired_promo_size, promo_limit);
@@ -649,7 +647,7 @@ void PSAdaptiveSizePolicy::adjust_promo_for_minor_pause_time(bool is_full_gc,
}
// If the desired eden size is as small as it will get,
// try to adjust the old gen size.
- if (*desired_eden_size_ptr <= _intra_generation_alignment) {
+ if (*desired_eden_size_ptr <= _space_alignment) {
// Vary the old gen size to reduce the young gen pause. This
// may not be a good idea. This is just a test.
if (minor_pause_old_estimator()->decrement_will_decrease()) {
@@ -754,7 +752,7 @@ void PSAdaptiveSizePolicy::adjust_eden_for_pause_time(bool is_full_gc,
// If the promo size is at the minimum (i.e., the old gen
// size will not actually decrease), consider changing the
// young gen size.
- if (*desired_promo_size_ptr < _intra_generation_alignment) {
+ if (*desired_promo_size_ptr < _space_alignment) {
// If increasing the young generation will decrease the old gen
// pause, do it.
// During startup there is noise in the statistics for deciding
@@ -1065,24 +1063,24 @@ size_t PSAdaptiveSizePolicy::eden_increment(size_t cur_eden) {
size_t PSAdaptiveSizePolicy::eden_increment_aligned_up(size_t cur_eden) {
size_t result = eden_increment(cur_eden, YoungGenerationSizeIncrement);
- return align_size_up(result, _intra_generation_alignment);
+ return align_size_up(result, _space_alignment);
}
size_t PSAdaptiveSizePolicy::eden_increment_aligned_down(size_t cur_eden) {
size_t result = eden_increment(cur_eden);
- return align_size_down(result, _intra_generation_alignment);
+ return align_size_down(result, _space_alignment);
}
size_t PSAdaptiveSizePolicy::eden_increment_with_supplement_aligned_up(
size_t cur_eden) {
size_t result = eden_increment(cur_eden,
YoungGenerationSizeIncrement + _young_gen_size_increment_supplement);
- return align_size_up(result, _intra_generation_alignment);
+ return align_size_up(result, _space_alignment);
}
size_t PSAdaptiveSizePolicy::eden_decrement_aligned_down(size_t cur_eden) {
size_t eden_heap_delta = eden_decrement(cur_eden);
- return align_size_down(eden_heap_delta, _intra_generation_alignment);
+ return align_size_down(eden_heap_delta, _space_alignment);
}
size_t PSAdaptiveSizePolicy::eden_decrement(size_t cur_eden) {
@@ -1104,24 +1102,24 @@ size_t PSAdaptiveSizePolicy::promo_increment(size_t cur_promo) {
size_t PSAdaptiveSizePolicy::promo_increment_aligned_up(size_t cur_promo) {
size_t result = promo_increment(cur_promo, TenuredGenerationSizeIncrement);
- return align_size_up(result, _intra_generation_alignment);
+ return align_size_up(result, _space_alignment);
}
size_t PSAdaptiveSizePolicy::promo_increment_aligned_down(size_t cur_promo) {
size_t result = promo_increment(cur_promo, TenuredGenerationSizeIncrement);
- return align_size_down(result, _intra_generation_alignment);
+ return align_size_down(result, _space_alignment);
}
size_t PSAdaptiveSizePolicy::promo_increment_with_supplement_aligned_up(
size_t cur_promo) {
size_t result = promo_increment(cur_promo,
TenuredGenerationSizeIncrement + _old_gen_size_increment_supplement);
- return align_size_up(result, _intra_generation_alignment);
+ return align_size_up(result, _space_alignment);
}
size_t PSAdaptiveSizePolicy::promo_decrement_aligned_down(size_t cur_promo) {
size_t promo_heap_delta = promo_decrement(cur_promo);
- return align_size_down(promo_heap_delta, _intra_generation_alignment);
+ return align_size_down(promo_heap_delta, _space_alignment);
}
size_t PSAdaptiveSizePolicy::promo_decrement(size_t cur_promo) {
@@ -1134,9 +1132,9 @@ uint PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold(
bool is_survivor_overflow,
uint tenuring_threshold,
size_t survivor_limit) {
- assert(survivor_limit >= _intra_generation_alignment,
+ assert(survivor_limit >= _space_alignment,
"survivor_limit too small");
- assert((size_t)align_size_down(survivor_limit, _intra_generation_alignment)
+ assert((size_t)align_size_down(survivor_limit, _space_alignment)
== survivor_limit, "survivor_limit not aligned");
// This method is called even if the tenuring threshold and survivor
@@ -1200,8 +1198,8 @@ uint PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold(
// We're trying to pad the survivor size as little as possible without
// overflowing the survivor spaces.
size_t target_size = align_size_up((size_t)_avg_survived->padded_average(),
- _intra_generation_alignment);
- target_size = MAX2(target_size, _intra_generation_alignment);
+ _space_alignment);
+ target_size = MAX2(target_size, _space_alignment);
if (target_size > survivor_limit) {
// Target size is bigger than we can handle. Let's also reduce
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp
index d88af2bf6ef..3389911876f 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp
@@ -91,7 +91,7 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
// for making ergonomic decisions.
double _latest_major_mutator_interval_seconds;
- const size_t _intra_generation_alignment; // alignment for eden, survivors
+ const size_t _space_alignment; // alignment for eden, survivors
const double _gc_minor_pause_goal_sec; // goal for maximum minor gc pause
@@ -229,7 +229,7 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
PSAdaptiveSizePolicy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size,
- size_t intra_generation_alignment,
+ size_t space_alignment,
double gc_pause_goal_sec,
double gc_minor_pause_goal_sec,
uint gc_time_ratio);
@@ -378,7 +378,7 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
// remain almost full anyway (top() will be near end(), but there will be a
// large filler object at the bottom).
const size_t sz = gen_size / MinSurvivorRatio;
- const size_t alignment = _intra_generation_alignment;
+ const size_t alignment = _space_alignment;
return sz > alignment ? align_size_down(sz, alignment) : alignment;
}
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp
index 2d8697587ac..c1f5c298794 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp
@@ -103,7 +103,7 @@ void PSYoungGen::initialize_work() {
// Compute maximum space sizes for performance counters
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- size_t alignment = heap->intra_heap_alignment();
+ size_t alignment = heap->space_alignment();
size_t size = virtual_space()->reserved_size();
size_t max_survivor_size;
@@ -156,8 +156,9 @@ void PSYoungGen::compute_initial_space_boundaries() {
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
// Compute sizes
- size_t alignment = heap->intra_heap_alignment();
+ size_t alignment = heap->space_alignment();
size_t size = virtual_space()->committed_size();
+ assert(size >= 3 * alignment, "Young space is not large enough for eden + 2 survivors");
size_t survivor_size = size / InitialSurvivorRatio;
survivor_size = align_size_down(survivor_size, alignment);
@@ -207,7 +208,7 @@ void PSYoungGen::set_space_boundaries(size_t eden_size, size_t survivor_size) {
#ifndef PRODUCT
void PSYoungGen::space_invariants() {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t alignment = heap->intra_heap_alignment();
+ const size_t alignment = heap->space_alignment();
// Currently, our eden size cannot shrink to zero
guarantee(eden_space()->capacity_in_bytes() >= alignment, "eden too small");
@@ -491,7 +492,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size,
char* to_end = (char*)to_space()->end();
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t alignment = heap->intra_heap_alignment();
+ const size_t alignment = heap->space_alignment();
const bool maintain_minimum =
(requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
@@ -840,8 +841,8 @@ size_t PSYoungGen::available_to_min_gen() {
size_t PSYoungGen::available_to_live() {
size_t delta_in_survivor = 0;
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
- const size_t space_alignment = heap->intra_heap_alignment();
- const size_t gen_alignment = heap->young_gen_alignment();
+ const size_t space_alignment = heap->space_alignment();
+ const size_t gen_alignment = heap->generation_alignment();
MutableSpace* space_shrinking = NULL;
if (from_space()->end() > to_space()->end()) {
diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp
index bbf5419fd0f..742e3b73be8 100644
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp
@@ -469,6 +469,10 @@ void CollectedHeap::fill_with_objects(HeapWord* start, size_t words, bool zap)
fill_with_object_impl(start, words, zap);
}
+void CollectedHeap::post_initialize() {
+ collector_policy()->post_heap_initialize();
+}
+
HeapWord* CollectedHeap::allocate_new_tlab(size_t size) {
guarantee(false, "thread-local allocation buffers not supported");
return NULL;
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp
index 8cd11de6ef2..8c3e95a0550 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp
@@ -47,54 +47,107 @@
// CollectorPolicy methods.
-void CollectorPolicy::initialize_flags() {
- assert(_max_alignment >= _min_alignment,
- err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT,
- _max_alignment, _min_alignment));
- assert(_max_alignment % _min_alignment == 0,
- err_msg("max_alignment: " SIZE_FORMAT " not aligned by min_alignment: " SIZE_FORMAT,
- _max_alignment, _min_alignment));
+CollectorPolicy::CollectorPolicy() :
+ _space_alignment(0),
+ _heap_alignment(0),
+ _initial_heap_byte_size(InitialHeapSize),
+ _max_heap_byte_size(MaxHeapSize),
+ _min_heap_byte_size(Arguments::min_heap_size()),
+ _max_heap_size_cmdline(false),
+ _size_policy(NULL),
+ _should_clear_all_soft_refs(false),
+ _all_soft_refs_clear(false)
+{}
- if (MaxHeapSize < InitialHeapSize) {
- vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
- }
-
- MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, _min_alignment);
+#ifdef ASSERT
+void CollectorPolicy::assert_flags() {
+ assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
+ assert(InitialHeapSize % _heap_alignment == 0, "InitialHeapSize alignment");
+ assert(MaxHeapSize % _heap_alignment == 0, "MaxHeapSize alignment");
}
-void CollectorPolicy::initialize_size_info() {
- // User inputs from -mx and ms must be aligned
- _min_heap_byte_size = align_size_up(Arguments::min_heap_size(), _min_alignment);
- _initial_heap_byte_size = align_size_up(InitialHeapSize, _min_alignment);
- _max_heap_byte_size = align_size_up(MaxHeapSize, _max_alignment);
+void CollectorPolicy::assert_size_info() {
+ assert(InitialHeapSize == _initial_heap_byte_size, "Discrepancy between InitialHeapSize flag and local storage");
+ assert(MaxHeapSize == _max_heap_byte_size, "Discrepancy between MaxHeapSize flag and local storage");
+ assert(_max_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible minimum and maximum heap sizes");
+ assert(_initial_heap_byte_size >= _min_heap_byte_size, "Ergonomics decided on incompatible initial and minimum heap sizes");
+ assert(_max_heap_byte_size >= _initial_heap_byte_size, "Ergonomics decided on incompatible initial and maximum heap sizes");
+ assert(_min_heap_byte_size % _heap_alignment == 0, "min_heap_byte_size alignment");
+ assert(_initial_heap_byte_size % _heap_alignment == 0, "initial_heap_byte_size alignment");
+ assert(_max_heap_byte_size % _heap_alignment == 0, "max_heap_byte_size alignment");
+}
+#endif // ASSERT
+
+void CollectorPolicy::initialize_flags() {
+ assert(_space_alignment != 0, "Space alignment not set up properly");
+ assert(_heap_alignment != 0, "Heap alignment not set up properly");
+ assert(_heap_alignment >= _space_alignment,
+ err_msg("heap_alignment: " SIZE_FORMAT " less than space_alignment: " SIZE_FORMAT,
+ _heap_alignment, _space_alignment));
+ assert(_heap_alignment % _space_alignment == 0,
+ err_msg("heap_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
+ _heap_alignment, _space_alignment));
+
+ if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+ if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
+ vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
+ }
+ if (_min_heap_byte_size != 0 && MaxHeapSize < _min_heap_byte_size) {
+ vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
+ }
+ _max_heap_size_cmdline = true;
+ }
// Check heap parameter properties
- if (_initial_heap_byte_size < M) {
+ if (InitialHeapSize < M) {
vm_exit_during_initialization("Too small initial heap");
}
- // Check heap parameter properties
if (_min_heap_byte_size < M) {
vm_exit_during_initialization("Too small minimum heap");
}
- if (_initial_heap_byte_size <= NewSize) {
- // make sure there is at least some room in old space
- vm_exit_during_initialization("Too small initial heap for new size specified");
+
+ // User inputs from -Xmx and -Xms must be aligned
+ _min_heap_byte_size = align_size_up(_min_heap_byte_size, _heap_alignment);
+ uintx aligned_initial_heap_size = align_size_up(InitialHeapSize, _heap_alignment);
+ uintx aligned_max_heap_size = align_size_up(MaxHeapSize, _heap_alignment);
+
+ // Write back to flags if the values changed
+ if (aligned_initial_heap_size != InitialHeapSize) {
+ FLAG_SET_ERGO(uintx, InitialHeapSize, aligned_initial_heap_size);
}
- if (_max_heap_byte_size < _min_heap_byte_size) {
- vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
- }
- if (_initial_heap_byte_size < _min_heap_byte_size) {
- vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
- }
- if (_max_heap_byte_size < _initial_heap_byte_size) {
- vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
+ if (aligned_max_heap_size != MaxHeapSize) {
+ FLAG_SET_ERGO(uintx, MaxHeapSize, aligned_max_heap_size);
}
+ if (FLAG_IS_CMDLINE(InitialHeapSize) && _min_heap_byte_size != 0 &&
+ InitialHeapSize < _min_heap_byte_size) {
+ vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
+ }
+ if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
+ FLAG_SET_ERGO(uintx, MaxHeapSize, InitialHeapSize);
+ } else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) {
+ FLAG_SET_ERGO(uintx, InitialHeapSize, MaxHeapSize);
+ if (InitialHeapSize < _min_heap_byte_size) {
+ _min_heap_byte_size = InitialHeapSize;
+ }
+ }
+
+ _initial_heap_byte_size = InitialHeapSize;
+ _max_heap_byte_size = MaxHeapSize;
+
+ FLAG_SET_ERGO(uintx, MinHeapDeltaBytes, align_size_up(MinHeapDeltaBytes, _space_alignment));
+
+ DEBUG_ONLY(CollectorPolicy::assert_flags();)
+}
+
+void CollectorPolicy::initialize_size_info() {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
SIZE_FORMAT " Maximum heap " SIZE_FORMAT,
_min_heap_byte_size, _initial_heap_byte_size, _max_heap_byte_size);
}
+
+ DEBUG_ONLY(CollectorPolicy::assert_size_info();)
}
bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) {
@@ -118,7 +171,7 @@ void CollectorPolicy::cleared_all_soft_refs() {
_all_soft_refs_clear = true;
}
-size_t CollectorPolicy::compute_max_alignment() {
+size_t CollectorPolicy::compute_heap_alignment() {
// The card marking array and the offset arrays for old generations are
// committed in os pages as well. Make sure they are entirely full (to
// avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
@@ -145,14 +198,21 @@ size_t CollectorPolicy::compute_max_alignment() {
// GenCollectorPolicy methods.
+GenCollectorPolicy::GenCollectorPolicy() :
+ _min_gen0_size(0),
+ _initial_gen0_size(0),
+ _max_gen0_size(0),
+ _gen_alignment(0),
+ _generations(NULL)
+{}
+
size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
- return align_size_down_bounded(base_size / (NewRatio + 1), _min_alignment);
+ return align_size_down_bounded(base_size / (NewRatio + 1), _gen_alignment);
}
size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
size_t maximum_size) {
- size_t alignment = _min_alignment;
- size_t max_minus = maximum_size - alignment;
+ size_t max_minus = maximum_size - _gen_alignment;
return desired_size < max_minus ? desired_size : max_minus;
}
@@ -168,101 +228,181 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
GCTimeRatio);
}
-void GenCollectorPolicy::initialize_flags() {
- // All sizes must be multiples of the generation granularity.
- _min_alignment = (uintx) Generation::GenGrain;
- _max_alignment = compute_max_alignment();
+size_t GenCollectorPolicy::young_gen_size_lower_bound() {
+ // The young generation must be aligned and have room for eden + two survivors
+ return align_size_up(3 * _space_alignment, _gen_alignment);
+}
+#ifdef ASSERT
+void GenCollectorPolicy::assert_flags() {
+ CollectorPolicy::assert_flags();
+ assert(NewSize >= _min_gen0_size, "Ergonomics decided on a too small young gen size");
+ assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
+ assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes");
+ assert(NewSize % _gen_alignment == 0, "NewSize alignment");
+ assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % _gen_alignment == 0, "MaxNewSize alignment");
+}
+
+void TwoGenerationCollectorPolicy::assert_flags() {
+ GenCollectorPolicy::assert_flags();
+ assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes");
+ assert(OldSize % _gen_alignment == 0, "OldSize alignment");
+}
+
+void GenCollectorPolicy::assert_size_info() {
+ CollectorPolicy::assert_size_info();
+ // GenCollectorPolicy::initialize_size_info may update the MaxNewSize
+ assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes");
+ assert(NewSize == _initial_gen0_size, "Discrepancy between NewSize flag and local storage");
+ assert(MaxNewSize == _max_gen0_size, "Discrepancy between MaxNewSize flag and local storage");
+ assert(_min_gen0_size <= _initial_gen0_size, "Ergonomics decided on incompatible minimum and initial young gen sizes");
+ assert(_initial_gen0_size <= _max_gen0_size, "Ergonomics decided on incompatible initial and maximum young gen sizes");
+ assert(_min_gen0_size % _gen_alignment == 0, "_min_gen0_size alignment");
+ assert(_initial_gen0_size % _gen_alignment == 0, "_initial_gen0_size alignment");
+ assert(_max_gen0_size % _gen_alignment == 0, "_max_gen0_size alignment");
+}
+
+void TwoGenerationCollectorPolicy::assert_size_info() {
+ GenCollectorPolicy::assert_size_info();
+ assert(OldSize == _initial_gen1_size, "Discrepancy between OldSize flag and local storage");
+ assert(_min_gen1_size <= _initial_gen1_size, "Ergonomics decided on incompatible minimum and initial old gen sizes");
+ assert(_initial_gen1_size <= _max_gen1_size, "Ergonomics decided on incompatible initial and maximum old gen sizes");
+ assert(_max_gen1_size % _gen_alignment == 0, "_max_gen1_size alignment");
+ assert(_initial_gen1_size % _gen_alignment == 0, "_initial_gen1_size alignment");
+ assert(_max_heap_byte_size <= (_max_gen0_size + _max_gen1_size), "Total maximum heap sizes must be sum of generation maximum sizes");
+}
+#endif // ASSERT
+
+void GenCollectorPolicy::initialize_flags() {
CollectorPolicy::initialize_flags();
- // All generational heaps have a youngest gen; handle those flags here.
+ assert(_gen_alignment != 0, "Generation alignment not set up properly");
+ assert(_heap_alignment >= _gen_alignment,
+ err_msg("heap_alignment: " SIZE_FORMAT " less than gen_alignment: " SIZE_FORMAT,
+ _heap_alignment, _gen_alignment));
+ assert(_gen_alignment % _space_alignment == 0,
+ err_msg("gen_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
+ _gen_alignment, _space_alignment));
+ assert(_heap_alignment % _gen_alignment == 0,
+ err_msg("heap_alignment: " SIZE_FORMAT " not aligned by gen_alignment: " SIZE_FORMAT,
+ _heap_alignment, _gen_alignment));
- // Adjust max size parameters
- if (NewSize > MaxNewSize) {
- MaxNewSize = NewSize;
+ // All generational heaps have a youngest gen; handle those flags here
+
+ // Make sure the heap is large enough for two generations
+ uintx smallest_new_size = young_gen_size_lower_bound();
+ uintx smallest_heap_size = align_size_up(smallest_new_size + align_size_up(_space_alignment, _gen_alignment),
+ _heap_alignment);
+ if (MaxHeapSize < smallest_heap_size) {
+ FLAG_SET_ERGO(uintx, MaxHeapSize, smallest_heap_size);
+ _max_heap_byte_size = MaxHeapSize;
+ }
+ // If needed, synchronize _min_heap_byte size and _initial_heap_byte_size
+ if (_min_heap_byte_size < smallest_heap_size) {
+ _min_heap_byte_size = smallest_heap_size;
+ if (InitialHeapSize < _min_heap_byte_size) {
+ FLAG_SET_ERGO(uintx, InitialHeapSize, smallest_heap_size);
+ _initial_heap_byte_size = smallest_heap_size;
+ }
}
- NewSize = align_size_down(NewSize, _min_alignment);
- MaxNewSize = align_size_down(MaxNewSize, _min_alignment);
- // Check validity of heap flags
- assert(NewSize % _min_alignment == 0, "eden space alignment");
- assert(MaxNewSize % _min_alignment == 0, "survivor space alignment");
+ // Now take the actual NewSize into account. We will silently increase NewSize
+ // if the user specified a smaller value.
+ smallest_new_size = MAX2(smallest_new_size, (uintx)align_size_down(NewSize, _gen_alignment));
+ if (smallest_new_size != NewSize) {
+ FLAG_SET_ERGO(uintx, NewSize, smallest_new_size);
+ }
+ _initial_gen0_size = NewSize;
- if (NewSize < 3 * _min_alignment) {
- // make sure there room for eden and two survivor spaces
- vm_exit_during_initialization("Too small new size specified");
+ if (!FLAG_IS_DEFAULT(MaxNewSize)) {
+ uintx min_new_size = MAX2(_gen_alignment, _min_gen0_size);
+
+ if (MaxNewSize >= MaxHeapSize) {
+ // Make sure there is room for an old generation
+ uintx smaller_max_new_size = MaxHeapSize - _gen_alignment;
+ if (FLAG_IS_CMDLINE(MaxNewSize)) {
+ warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or greater than the entire "
+ "heap (" SIZE_FORMAT "k). A new max generation size of " SIZE_FORMAT "k will be used.",
+ MaxNewSize/K, MaxHeapSize/K, smaller_max_new_size/K);
+ }
+ FLAG_SET_ERGO(uintx, MaxNewSize, smaller_max_new_size);
+ if (NewSize > MaxNewSize) {
+ FLAG_SET_ERGO(uintx, NewSize, MaxNewSize);
+ _initial_gen0_size = NewSize;
+ }
+ } else if (MaxNewSize < min_new_size) {
+ FLAG_SET_ERGO(uintx, MaxNewSize, min_new_size);
+ } else if (!is_size_aligned(MaxNewSize, _gen_alignment)) {
+ FLAG_SET_ERGO(uintx, MaxNewSize, align_size_down(MaxNewSize, _gen_alignment));
+ }
+ _max_gen0_size = MaxNewSize;
+ }
+
+ if (NewSize > MaxNewSize) {
+ // At this point this should only happen if the user specifies a large NewSize and/or
+ // a small (but not too small) MaxNewSize.
+ if (FLAG_IS_CMDLINE(MaxNewSize)) {
+ warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). "
+ "A new max generation size of " SIZE_FORMAT "k will be used.",
+ NewSize/K, MaxNewSize/K, NewSize/K);
+ }
+ FLAG_SET_ERGO(uintx, MaxNewSize, NewSize);
+ _max_gen0_size = MaxNewSize;
}
if (SurvivorRatio < 1 || NewRatio < 1) {
vm_exit_during_initialization("Invalid young gen ratio specified");
}
+
+ DEBUG_ONLY(GenCollectorPolicy::assert_flags();)
}
void TwoGenerationCollectorPolicy::initialize_flags() {
GenCollectorPolicy::initialize_flags();
- OldSize = align_size_down(OldSize, _min_alignment);
+ if (!is_size_aligned(OldSize, _gen_alignment)) {
+ FLAG_SET_ERGO(uintx, OldSize, align_size_down(OldSize, _gen_alignment));
+ }
- if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) {
+ if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) {
// NewRatio will be used later to set the young generation size so we use
// it to calculate how big the heap should be based on the requested OldSize
// and NewRatio.
assert(NewRatio > 0, "NewRatio should have been set up earlier");
size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1);
- calculated_heapsize = align_size_up(calculated_heapsize, _max_alignment);
- MaxHeapSize = calculated_heapsize;
- InitialHeapSize = calculated_heapsize;
+ calculated_heapsize = align_size_up(calculated_heapsize, _heap_alignment);
+ FLAG_SET_ERGO(uintx, MaxHeapSize, calculated_heapsize);
+ _max_heap_byte_size = MaxHeapSize;
+ FLAG_SET_ERGO(uintx, InitialHeapSize, calculated_heapsize);
+ _initial_heap_byte_size = InitialHeapSize;
}
- MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
// adjust max heap size if necessary
if (NewSize + OldSize > MaxHeapSize) {
- if (FLAG_IS_CMDLINE(MaxHeapSize)) {
+ if (_max_heap_size_cmdline) {
// somebody set a maximum heap size with the intention that we should not
// exceed it. Adjust New/OldSize as necessary.
uintx calculated_size = NewSize + OldSize;
double shrink_factor = (double) MaxHeapSize / calculated_size;
- // align
- NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment);
- // OldSize is already aligned because above we aligned MaxHeapSize to
- // _max_alignment, and we just made sure that NewSize is aligned to
- // _min_alignment. In initialize_flags() we verified that _max_alignment
- // is a multiple of _min_alignment.
- OldSize = MaxHeapSize - NewSize;
- } else {
- MaxHeapSize = NewSize + OldSize;
- }
- }
- // need to do this again
- MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
+ uintx smaller_new_size = align_size_down((uintx)(NewSize * shrink_factor), _gen_alignment);
+ FLAG_SET_ERGO(uintx, NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size));
+ _initial_gen0_size = NewSize;
- // adjust max heap size if necessary
- if (NewSize + OldSize > MaxHeapSize) {
- if (FLAG_IS_CMDLINE(MaxHeapSize)) {
- // somebody set a maximum heap size with the intention that we should not
- // exceed it. Adjust New/OldSize as necessary.
- uintx calculated_size = NewSize + OldSize;
- double shrink_factor = (double) MaxHeapSize / calculated_size;
- // align
- NewSize = align_size_down((uintx) (NewSize * shrink_factor), _min_alignment);
// OldSize is already aligned because above we aligned MaxHeapSize to
- // _max_alignment, and we just made sure that NewSize is aligned to
- // _min_alignment. In initialize_flags() we verified that _max_alignment
- // is a multiple of _min_alignment.
- OldSize = MaxHeapSize - NewSize;
+ // _heap_alignment, and we just made sure that NewSize is aligned to
+ // _gen_alignment. In initialize_flags() we verified that _heap_alignment
+ // is a multiple of _gen_alignment.
+ FLAG_SET_ERGO(uintx, OldSize, MaxHeapSize - NewSize);
} else {
- MaxHeapSize = NewSize + OldSize;
+ FLAG_SET_ERGO(uintx, MaxHeapSize, align_size_up(NewSize + OldSize, _heap_alignment));
+ _max_heap_byte_size = MaxHeapSize;
}
}
- // need to do this again
- MaxHeapSize = align_size_up(MaxHeapSize, _max_alignment);
always_do_update_barrier = UseConcMarkSweepGC;
- // Check validity of heap flags
- assert(OldSize % _min_alignment == 0, "old space alignment");
- assert(MaxHeapSize % _max_alignment == 0, "maximum heap alignment");
+ DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_flags();)
}
// Values set on the command line win over any ergonomically
@@ -277,7 +417,7 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
void GenCollectorPolicy::initialize_size_info() {
CollectorPolicy::initialize_size_info();
- // _min_alignment is used for alignment within a generation.
+ // _space_alignment is used for alignment within a generation.
// There is additional alignment done down stream for some
// collectors that sometimes causes unwanted rounding up of
// generations sizes.
@@ -285,35 +425,8 @@ void GenCollectorPolicy::initialize_size_info() {
// Determine maximum size of gen0
size_t max_new_size = 0;
- if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) {
- if (MaxNewSize < _min_alignment) {
- max_new_size = _min_alignment;
- }
- if (MaxNewSize >= _max_heap_byte_size) {
- max_new_size = align_size_down(_max_heap_byte_size - _min_alignment,
- _min_alignment);
- warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
- "greater than the entire heap (" SIZE_FORMAT "k). A "
- "new generation size of " SIZE_FORMAT "k will be used.",
- MaxNewSize/K, _max_heap_byte_size/K, max_new_size/K);
- } else {
- max_new_size = align_size_down(MaxNewSize, _min_alignment);
- }
-
- // The case for FLAG_IS_ERGO(MaxNewSize) could be treated
- // specially at this point to just use an ergonomically set
- // MaxNewSize to set max_new_size. For cases with small
- // heaps such a policy often did not work because the MaxNewSize
- // was larger than the entire heap. The interpretation given
- // to ergonomically set flags is that the flags are set
- // by different collectors for their own special needs but
- // are not allowed to badly shape the heap. This allows the
- // different collectors to decide what's best for themselves
- // without having to factor in the overall heap shape. It
- // can be the case in the future that the collectors would
- // only make "wise" ergonomics choices and this policy could
- // just accept those choices. The choices currently made are
- // not always "wise".
+ if (!FLAG_IS_DEFAULT(MaxNewSize)) {
+ max_new_size = MaxNewSize;
} else {
max_new_size = scale_by_NewRatio_aligned(_max_heap_byte_size);
// Bound the maximum size by NewSize below (since it historically
@@ -382,11 +495,22 @@ void GenCollectorPolicy::initialize_size_info() {
_min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size);
}
+ // Write back to flags if necessary
+ if (NewSize != _initial_gen0_size) {
+ FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size);
+ }
+
+ if (MaxNewSize != _max_gen0_size) {
+ FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size);
+ }
+
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
_min_gen0_size, _initial_gen0_size, _max_gen0_size);
}
+
+ DEBUG_ONLY(GenCollectorPolicy::assert_size_info();)
}
// Call this method during the sizing of the gen1 to make
@@ -404,14 +528,15 @@ bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
bool result = false;
if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
+ uintx smallest_new_size = young_gen_size_lower_bound();
if ((heap_size < (*gen0_size_ptr + min_gen1_size)) &&
- (heap_size >= min_gen1_size + _min_alignment)) {
+ (heap_size >= min_gen1_size + smallest_new_size)) {
// Adjust gen0 down to accommodate min_gen1_size
- *gen0_size_ptr = align_size_down_bounded(heap_size - min_gen1_size, _min_alignment);
+ *gen0_size_ptr = align_size_down_bounded(heap_size - min_gen1_size, _gen_alignment);
assert(*gen0_size_ptr > 0, "Min gen0 is too large");
result = true;
} else {
- *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _min_alignment);
+ *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _gen_alignment);
}
}
return result;
@@ -432,36 +557,31 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
// The maximum gen1 size can be determined from the maximum gen0
// and maximum heap size since no explicit flags exits
// for setting the gen1 maximum.
- _max_gen1_size = _max_heap_byte_size - _max_gen0_size;
- _max_gen1_size =
- MAX2((uintx)align_size_down(_max_gen1_size, _min_alignment), _min_alignment);
+ _max_gen1_size = MAX2(_max_heap_byte_size - _max_gen0_size, _gen_alignment);
+
// If no explicit command line flag has been set for the
// gen1 size, use what is left for gen1.
- if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
- // The user has not specified any value or ergonomics
- // has chosen a value (which may or may not be consistent
+ if (!FLAG_IS_CMDLINE(OldSize)) {
+ // The user has not specified any value but the ergonomics
+ // may have chosen a value (which may or may not be consistent
// with the overall heap size). In either case make
// the minimum, maximum and initial sizes consistent
// with the gen0 sizes and the overall heap sizes.
- assert(_min_heap_byte_size > _min_gen0_size,
- "gen0 has an unexpected minimum size");
- _min_gen1_size = _min_heap_byte_size - _min_gen0_size;
- _min_gen1_size =
- MAX2((uintx)align_size_down(_min_gen1_size, _min_alignment), _min_alignment);
- _initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
- _initial_gen1_size =
- MAX2((uintx)align_size_down(_initial_gen1_size, _min_alignment), _min_alignment);
+ _min_gen1_size = MAX2(_min_heap_byte_size - _min_gen0_size, _gen_alignment);
+ _initial_gen1_size = MAX2(_initial_heap_byte_size - _initial_gen0_size, _gen_alignment);
+ // _max_gen1_size has already been made consistent above
+ FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size);
} else {
// It's been explicitly set on the command line. Use the
// OldSize and then determine the consequences.
- _min_gen1_size = OldSize;
+ _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size);
_initial_gen1_size = OldSize;
// If the user has explicitly set an OldSize that is inconsistent
// with other command line flags, issue a warning.
// The generation minimums and the overall heap mimimum should
- // be within one heap alignment.
- if ((_min_gen1_size + _min_gen0_size + _min_alignment) < _min_heap_byte_size) {
+ // be within one generation alignment.
+ if ((_min_gen1_size + _min_gen0_size + _gen_alignment) < _min_heap_byte_size) {
warning("Inconsistency between minimum heap size and minimum "
"generation sizes: using minimum heap = " SIZE_FORMAT,
_min_heap_byte_size);
@@ -475,7 +595,7 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
// If there is an inconsistency between the OldSize and the minimum and/or
// initial size of gen0, since OldSize was explicitly set, OldSize wins.
if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
- _min_heap_byte_size, OldSize)) {
+ _min_heap_byte_size, _min_gen1_size)) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
@@ -484,7 +604,7 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
}
// Initial size
if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
- _initial_heap_byte_size, OldSize)) {
+ _initial_heap_byte_size, _initial_gen1_size)) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 "
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
@@ -499,11 +619,26 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
_initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size);
_initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size);
+ // Write back to flags if necessary
+ if (NewSize != _initial_gen0_size) {
+ FLAG_SET_ERGO(uintx, NewSize, _max_gen0_size);
+ }
+
+ if (MaxNewSize != _max_gen0_size) {
+ FLAG_SET_ERGO(uintx, MaxNewSize, _max_gen0_size);
+ }
+
+ if (OldSize != _initial_gen1_size) {
+ FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size);
+ }
+
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 "
SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT,
_min_gen1_size, _initial_gen1_size, _max_gen1_size);
}
+
+ DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_size_info();)
}
HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
@@ -826,8 +961,9 @@ bool GenCollectorPolicy::should_try_older_generation_allocation(
// MarkSweepPolicy methods
//
-MarkSweepPolicy::MarkSweepPolicy() {
- initialize_all();
+void MarkSweepPolicy::initialize_alignments() {
+ _space_alignment = _gen_alignment = (uintx)Generation::GenGrain;
+ _heap_alignment = compute_heap_alignment();
}
void MarkSweepPolicy::initialize_generations() {
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp
index bbfccdd644c..509702319d0 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.hpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp
@@ -61,17 +61,23 @@ class CollectorPolicy : public CHeapObj {
protected:
GCPolicyCounters* _gc_policy_counters;
- // Requires that the concrete subclass sets the alignment constraints
- // before calling.
+ virtual void initialize_alignments() = 0;
virtual void initialize_flags();
virtual void initialize_size_info();
+ DEBUG_ONLY(virtual void assert_flags();)
+ DEBUG_ONLY(virtual void assert_size_info();)
+
size_t _initial_heap_byte_size;
size_t _max_heap_byte_size;
size_t _min_heap_byte_size;
- size_t _min_alignment;
- size_t _max_alignment;
+ size_t _space_alignment;
+ size_t _heap_alignment;
+
+ // Needed to keep information if MaxHeapSize was set on the command line
+ // when the flag value is aligned etc by ergonomics
+ bool _max_heap_size_cmdline;
// The sizing of the heap are controlled by a sizing policy.
AdaptiveSizePolicy* _size_policy;
@@ -87,23 +93,20 @@ class CollectorPolicy : public CHeapObj {
// mem_allocate() where it returns op.result()
bool _all_soft_refs_clear;
- CollectorPolicy() :
- _min_alignment(1),
- _max_alignment(1),
- _initial_heap_byte_size(0),
- _max_heap_byte_size(0),
- _min_heap_byte_size(0),
- _size_policy(NULL),
- _should_clear_all_soft_refs(false),
- _all_soft_refs_clear(false)
- {}
+ CollectorPolicy();
public:
- // Return maximum heap alignment that may be imposed by the policy
- static size_t compute_max_alignment();
+ virtual void initialize_all() {
+ initialize_alignments();
+ initialize_flags();
+ initialize_size_info();
+ }
- size_t min_alignment() { return _min_alignment; }
- size_t max_alignment() { return _max_alignment; }
+ // Return maximum heap alignment that may be imposed by the policy
+ static size_t compute_heap_alignment();
+
+ size_t space_alignment() { return _space_alignment; }
+ size_t heap_alignment() { return _heap_alignment; }
size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
size_t max_heap_byte_size() { return _max_heap_byte_size; }
@@ -195,6 +198,9 @@ class CollectorPolicy : public CHeapObj {
return false;
}
+ // Do any updates required to global flags that are due to heap initialization
+ // changes
+ virtual void post_heap_initialize() = 0;
};
class ClearedAllSoftRefs : public StackObj {
@@ -219,6 +225,10 @@ class GenCollectorPolicy : public CollectorPolicy {
size_t _initial_gen0_size;
size_t _max_gen0_size;
+ // _gen_alignment and _space_alignment will have the same value most of the
+ // time. When using large pages they can differ.
+ size_t _gen_alignment;
+
GenerationSpec **_generations;
// Return true if an allocation should be attempted in the older
@@ -229,23 +239,31 @@ class GenCollectorPolicy : public CollectorPolicy {
void initialize_flags();
void initialize_size_info();
+ DEBUG_ONLY(void assert_flags();)
+ DEBUG_ONLY(void assert_size_info();)
+
// Try to allocate space by expanding the heap.
virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab);
- // Scale the base_size by NewRation according to
+ // Compute max heap alignment
+ size_t compute_max_alignment();
+
+ // Scale the base_size by NewRatio according to
// result = base_size / (NewRatio + 1)
// and align by min_alignment()
size_t scale_by_NewRatio_aligned(size_t base_size);
- // Bound the value by the given maximum minus the
- // min_alignment.
+ // Bound the value by the given maximum minus the min_alignment
size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
public:
+ GenCollectorPolicy();
+
// Accessors
size_t min_gen0_size() { return _min_gen0_size; }
size_t initial_gen0_size() { return _initial_gen0_size; }
size_t max_gen0_size() { return _max_gen0_size; }
+ size_t gen_alignment() { return _gen_alignment; }
virtual int number_of_generations() = 0;
@@ -256,14 +274,15 @@ class GenCollectorPolicy : public CollectorPolicy {
virtual GenCollectorPolicy* as_generation_policy() { return this; }
- virtual void initialize_generations() = 0;
+ virtual void initialize_generations() { };
virtual void initialize_all() {
- initialize_flags();
- initialize_size_info();
+ CollectorPolicy::initialize_all();
initialize_generations();
}
+ size_t young_gen_size_lower_bound();
+
HeapWord* mem_allocate_work(size_t size,
bool is_tlab,
bool* gc_overhead_limit_was_exceeded);
@@ -275,10 +294,8 @@ class GenCollectorPolicy : public CollectorPolicy {
size_t init_promo_size,
size_t init_survivor_size);
- // The alignment used for eden and survivors within the young gen
- // and for boundary between young gen and old gen.
- static size_t intra_heap_alignment() {
- return 64 * K * HeapWordSize;
+ virtual void post_heap_initialize() {
+ assert(_max_gen0_size == MaxNewSize, "Should be taken care of by initialize_size_info");
}
};
@@ -296,9 +313,14 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
void initialize_flags();
void initialize_size_info();
- void initialize_generations() { ShouldNotReachHere(); }
+
+ DEBUG_ONLY(void assert_flags();)
+ DEBUG_ONLY(void assert_size_info();)
public:
+ TwoGenerationCollectorPolicy() : GenCollectorPolicy(), _min_gen1_size(0),
+ _initial_gen1_size(0), _max_gen1_size(0) {}
+
// Accessors
size_t min_gen1_size() { return _min_gen1_size; }
size_t initial_gen1_size() { return _initial_gen1_size; }
@@ -321,10 +343,11 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
class MarkSweepPolicy : public TwoGenerationCollectorPolicy {
protected:
+ void initialize_alignments();
void initialize_generations();
public:
- MarkSweepPolicy();
+ MarkSweepPolicy() {}
MarkSweepPolicy* as_mark_sweep_policy() { return this; }
diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp
index 0b4af29a3e3..ca3ff46b167 100644
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp
@@ -204,7 +204,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs,
// Compute the maximum eden and survivor space sizes. These sizes
// are computed assuming the entire reserved space is committed.
// These values are exported as performance counters.
- uintx alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment();
+ uintx alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
uintx size = _virtual_space.reserved_size();
_max_survivor_size = compute_survivor_size(size, alignment);
_max_eden_size = size - (2*_max_survivor_size);
@@ -235,7 +235,7 @@ void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size,
bool clear_space,
bool mangle_space) {
uintx alignment =
- GenCollectedHeap::heap()->collector_policy()->min_alignment();
+ GenCollectedHeap::heap()->collector_policy()->space_alignment();
// If the spaces are being cleared (only done at heap initialization
// currently), the survivor spaces need not be empty.
@@ -473,7 +473,7 @@ size_t DefNewGeneration::free() const {
}
size_t DefNewGeneration::max_capacity() const {
- const size_t alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment();
+ const size_t alignment = GenCollectedHeap::heap()->collector_policy()->space_alignment();
const size_t reserved_bytes = reserved().byte_size();
return reserved_bytes - compute_survivor_size(reserved_bytes, alignment);
}
diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp
index 2b84542ef48..aa6f24bd23e 100644
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp
@@ -111,7 +111,7 @@ jint GenCollectedHeap::initialize() {
int n_covered_regions = 0;
ReservedSpace heap_rs;
- size_t heap_alignment = collector_policy()->max_alignment();
+ size_t heap_alignment = collector_policy()->heap_alignment();
heap_address = allocate(heap_alignment, &total_reserved,
&n_covered_regions, &heap_rs);
diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp
index 79455db9b6e..47ebc180c8e 100644
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp
+++ b/hotspot/src/share/vm/memory/sharedHeap.cpp
@@ -247,6 +247,7 @@ void SharedHeap::set_barrier_set(BarrierSet* bs) {
}
void SharedHeap::post_initialize() {
+ CollectedHeap::post_initialize();
ref_processing_init();
}
diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp
index 18c9733076c..5dc76f703d3 100644
--- a/hotspot/src/share/vm/memory/universe.cpp
+++ b/hotspot/src/share/vm/memory/universe.cpp
@@ -765,6 +765,7 @@ jint Universe::initialize_heap() {
} else if (UseG1GC) {
#if INCLUDE_ALL_GCS
G1CollectorPolicy* g1p = new G1CollectorPolicy();
+ g1p->initialize_all();
G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
Universe::_collectedHeap = g1h;
#else // INCLUDE_ALL_GCS
@@ -789,6 +790,7 @@ jint Universe::initialize_heap() {
} else { // default old generation
gc_policy = new MarkSweepPolicy();
}
+ gc_policy->initialize_all();
Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
}
diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp
index 6f6a2000a3f..556de7ec96a 100644
--- a/hotspot/src/share/vm/prims/whitebox.cpp
+++ b/hotspot/src/share/vm/prims/whitebox.cpp
@@ -105,7 +105,7 @@ WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Min alignment "SIZE_FORMAT" Max alignment "SIZE_FORMAT,
p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
- p->min_alignment(), p->max_alignment());
+ p->space_alignment(), p->heap_alignment());
}
WB_END
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 1e82e5bdca8..39f94be5c79 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -1505,7 +1505,7 @@ void Arguments::set_conservative_max_heap_alignment() {
}
#endif // INCLUDE_ALL_GCS
_conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(),
- CollectorPolicy::compute_max_alignment());
+ CollectorPolicy::compute_heap_alignment());
}
void Arguments::set_ergonomics_flags() {
@@ -2165,6 +2165,10 @@ bool Arguments::check_vm_args_consistency() {
#if INCLUDE_ALL_GCS
if (UseG1GC) {
+ status = status && verify_percentage(G1NewSizePercent, "G1NewSizePercent");
+ status = status && verify_percentage(G1MaxNewSizePercent, "G1MaxNewSizePercent");
+ status = status && verify_interval(G1NewSizePercent, 0, G1MaxNewSizePercent, "G1NewSizePercent");
+
status = status && verify_percentage(InitiatingHeapOccupancyPercent,
"InitiatingHeapOccupancyPercent");
status = status && verify_min_value(G1RefProcDrainInterval, 1,
diff --git a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java
index cb7d841355e..0e07f794194 100644
--- a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java
+++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java
@@ -64,32 +64,29 @@ class TestMaxHeapSizeTools {
long newPlusOldSize = values[0] + values[1];
long smallValue = newPlusOldSize / 2;
long largeValue = newPlusOldSize * 2;
+ long maxHeapSize = largeValue + (2 * 1024 * 1024);
// -Xms is not set
- checkErgonomics(new String[] { gcflag, "-Xmx16M" }, values, -1, -1);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-XX:InitialHeapSize=0" }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1);
// -Xms is set to zero
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0" }, values, -1, -1);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
// -Xms is set to small value
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue }, values, -1, -1);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
// -Xms is set to large value
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue }, values, largeValue, largeValue);
- // the next case has already been checked elsewhere and gives an error
- // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
- // the next case has already been checked elsewhere too
- // checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=" + largeValue }, values, values[0], largeValue);
- checkErgonomics(new String[] { gcflag, "-Xmx16M", "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue);
+ checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
}
private static long align_up(long value, long alignment) {
diff --git a/hotspot/test/gc/arguments/TestMaxNewSize.java b/hotspot/test/gc/arguments/TestMaxNewSize.java
new file mode 100644
index 00000000000..af20cb819e3
--- /dev/null
+++ b/hotspot/test/gc/arguments/TestMaxNewSize.java
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 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.
+*
+* 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 TestMaxNewSize
+ * @key gc
+ * @bug 7057939
+ * @summary Make sure that MaxNewSize always has a useful value after argument
+ * processing.
+ * @library /testlibrary
+ * @build TestMaxNewSize
+ * @run main TestMaxNewSize -XX:+UseSerialGC
+ * @run main TestMaxNewSize -XX:+UseParallelGC
+ * @run main TestMaxNewSize -XX:+UseConcMarkSweepGC
+ * @run main TestMaxNewSize -XX:+UseG1GC
+ * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import java.math.BigInteger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.*;
+
+public class TestMaxNewSize {
+
+ private static void checkMaxNewSize(String[] flags, int heapsize) throws Exception {
+ BigInteger actual = new BigInteger(getMaxNewSize(flags));
+ System.out.println(actual);
+ if (actual.compareTo(new BigInteger((new Long(heapsize)).toString())) == 1) {
+ throw new RuntimeException("MaxNewSize value set to \"" + actual +
+ "\", expected otherwise when running with the following flags: " + Arrays.asList(flags).toString());
+ }
+ }
+
+ private static void checkIncompatibleNewSize(String[] flags) throws Exception {
+ ArrayList finalargs = new ArrayList();
+ finalargs.addAll(Arrays.asList(flags));
+ finalargs.add("-version");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Initial young gen size set larger than the maximum young gen size");
+ }
+
+ private static boolean isRunningG1(String[] args) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].contains("+UseG1GC")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static String getMaxNewSize(String[] flags) throws Exception {
+ ArrayList finalargs = new ArrayList();
+ finalargs.addAll(Arrays.asList(flags));
+ if (isRunningG1(flags)) {
+ finalargs.add("-XX:G1HeapRegionSize=1M");
+ }
+ finalargs.add("-XX:+PrintFlagsFinal");
+ finalargs.add("-version");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ String stdout = output.getStdout();
+ //System.out.println(stdout);
+ return getFlagValue("MaxNewSize", stdout);
+ }
+
+ private static String getFlagValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+ }
+ String match = m.group();
+ return match.substring(match.lastIndexOf(" ") + 1, match.length());
+ }
+
+ public static void main(String args[]) throws Exception {
+ String gcName = args[0];
+ final int M32 = 32 * 1024 * 1024;
+ final int M64 = 64 * 1024 * 1024;
+ final int M96 = 96 * 1024 * 1024;
+ final int M128 = 128 * 1024 * 1024;
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M" }, M128);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewRatio=5" }, M128);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewSize=32M" }, M128);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:OldSize=96M" }, M128);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:MaxNewSize=32M" }, M32);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewSize=32M", "-XX:MaxNewSize=32M" }, M32);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-XX:NewRatio=6", "-XX:MaxNewSize=32M" }, M32);
+ checkMaxNewSize(new String[] { gcName, "-Xmx128M", "-Xms96M" }, M128);
+ checkMaxNewSize(new String[] { gcName, "-Xmx96M", "-Xms96M" }, M96);
+ checkMaxNewSize(new String[] { gcName, "-XX:NewSize=128M", "-XX:MaxNewSize=50M"}, M128);
+ }
+}
From 53cdc28a02fcf3df17b2d07ce4cd289524ac4265 Mon Sep 17 00:00:00 2001
From: Sergey Malenkov
Date: Fri, 1 Nov 2013 21:45:02 +0400
Subject: [PATCH 008/110] 8026491: Typos in string literals
Reviewed-by: alexsch, anthony
---
.../macosx/classes/com/apple/laf/AquaFileChooserUI.java | 2 +-
.../classes/com/apple/laf/resources/aqua.properties | 2 +-
.../plugins/common/StandardMetadataFormatResources.java | 2 +-
.../sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java | 4 ++--
.../sun/jmx/snmp/daemon/SnmpSubNextRequestHandler.java | 4 ++--
.../com/sun/jmx/snmp/daemon/SnmpSubRequestHandler.java | 4 ++--
.../sun/tools/example/debug/gui/CommandInterpreter.java | 4 ++--
jdk/src/share/classes/com/sun/tools/script/shell/init.js | 2 +-
.../com/sun/tools/script/shell/messages.properties | 2 +-
.../javax/management/modelmbean/RequiredModelMBean.java | 4 ++--
jdk/src/share/classes/javax/swing/KeyboardManager.java | 2 +-
.../classes/javax/swing/SortingFocusTraversalPolicy.java | 2 +-
.../share/classes/javax/swing/text/AbstractDocument.java | 4 ++--
jdk/src/share/classes/sun/awt/AppContext.java | 2 +-
.../management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java | 4 ++--
jdk/src/share/classes/sun/misc/ExtensionDependency.java | 2 +-
jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java | 4 ++--
.../classes/sun/security/jgss/krb5/InitialToken.java | 2 +-
.../classes/sun/security/jgss/spnego/SpNegoContext.java | 8 ++++----
.../share/demo/jfc/FileChooserDemo/FileChooserDemo.java | 4 ++--
.../share/native/sun/security/pkcs11/wrapper/p11_util.c | 6 +++---
jdk/src/share/sample/nio/chatserver/ClientReader.java | 2 +-
jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java | 2 +-
.../windows/classes/sun/nio/ch/WindowsSelectorImpl.java | 2 +-
.../classes/sun/security/krb5/internal/tools/Klist.java | 2 +-
.../classes/sun/security/krb5/internal/tools/Ktab.java | 4 ++--
26 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java
index be4b5b72a32..5669d10b1a4 100644
--- a/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java
+++ b/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java
@@ -227,7 +227,7 @@ public class AquaFileChooserUI extends FileChooserUI {
// Exist in basic.properties (though we might want to override)
fileDescriptionText = UIManager.getString("FileChooser.fileDescriptionText");
directoryDescriptionText = UIManager.getString("FileChooser.directoryDescriptionText");
- newFolderErrorText = getString("FileChooser.newFolderErrorText", "Error occured during folder creation");
+ newFolderErrorText = getString("FileChooser.newFolderErrorText", "Error occurred during folder creation");
saveButtonText = UIManager.getString("FileChooser.saveButtonText");
openButtonText = UIManager.getString("FileChooser.openButtonText");
diff --git a/jdk/src/macosx/classes/com/apple/laf/resources/aqua.properties b/jdk/src/macosx/classes/com/apple/laf/resources/aqua.properties
index 17f7a94584a..ac147020ce7 100644
--- a/jdk/src/macosx/classes/com/apple/laf/resources/aqua.properties
+++ b/jdk/src/macosx/classes/com/apple/laf/resources/aqua.properties
@@ -38,7 +38,7 @@
############ FILE CHOOSER STRINGS #############
FileChooser.fileDescription.textAndMnemonic=Generic File
FileChooser.directoryDescription.textAndMnemonic=Directory
-FileChooser.newFolderError.textAndMnemonic=Error occured during folder creation
+FileChooser.newFolderError.textAndMnemonic=Error occurred during folder creation
FileChooser.newFolderErrorSeparator= :
FileChooser.acceptAllFileFilter.textAndMnemonic=All Files
FileChooser.cancelButton.textAndMnemonic=Cancel
diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java b/jdk/src/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java
index 96f099cf222..00bf1ee323e 100644
--- a/jdk/src/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/common/StandardMetadataFormatResources.java
@@ -123,7 +123,7 @@ public class StandardMetadataFormatResources extends ListResourceBundle {
"The vertical position, in millimeters, where the image should be rendered on media " },
{ "HorizontalPixelOffset",
- "The horizonal position, in pixels, where the image should be rendered onto a raster display" },
+ "The horizontal position, in pixels, where the image should be rendered onto a raster display" },
{ "VerticalPixelOffset",
"The vertical position, in pixels, where the image should be rendered onto a raster display" },
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java
index 6dc479f242c..aa349526456 100644
--- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java
@@ -111,7 +111,7 @@ class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
"run", "[" + Thread.currentThread() +
- "]:an Snmp error occured during the operation", x);
+ "]:an Snmp error occurred during the operation", x);
}
}
catch(Exception x) {
@@ -119,7 +119,7 @@ class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
"run", "[" + Thread.currentThread() +
- "]:a generic error occured during the operation", x);
+ "]:a generic error occurred during the operation", x);
}
}
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubNextRequestHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubNextRequestHandler.java
index 3ff95f6a001..99eebaa8c22 100644
--- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubNextRequestHandler.java
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubNextRequestHandler.java
@@ -127,7 +127,7 @@ class SnmpSubNextRequestHandler extends SnmpSubRequestHandler {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
"run", "[" + Thread.currentThread() +
- "]:an Snmp error occured during the operation", x);
+ "]:an Snmp error occurred during the operation", x);
}
}
catch(Exception x) {
@@ -135,7 +135,7 @@ class SnmpSubNextRequestHandler extends SnmpSubRequestHandler {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
"run", "[" + Thread.currentThread() +
- "]:a generic error occured during the operation", x);
+ "]:a generic error occurred during the operation", x);
}
}
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubRequestHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubRequestHandler.java
index 0b981311358..391d528f876 100644
--- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubRequestHandler.java
+++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubRequestHandler.java
@@ -231,7 +231,7 @@ class SnmpSubRequestHandler implements SnmpDefinitions, Runnable {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
"run", "[" + Thread.currentThread() +
- "]:an Snmp error occured during the operation", x);
+ "]:an Snmp error occurred during the operation", x);
}
}
catch(Exception x) {
@@ -239,7 +239,7 @@ class SnmpSubRequestHandler implements SnmpDefinitions, Runnable {
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
"run", "[" + Thread.currentThread() +
- "]:a generic error occured during the operation", x);
+ "]:a generic error occurred during the operation", x);
}
}
if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
diff --git a/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java b/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java
index b0494c282df..1b164209c82 100644
--- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java
+++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java
@@ -377,7 +377,7 @@ public class CommandInterpreter {
env.failure("Attempt to launch main class \"" + clname + "\" failed.");
}
} else {
- env.failure("No main class specifed and no current default defined.");
+ env.failure("No main class specified and no current default defined.");
}
} else {
clname = t.nextToken();
@@ -428,7 +428,7 @@ public class CommandInterpreter {
env.failure("Attempt to attach to port \"" + portName + "\" failed.");
}
} else {
- env.failure("No port specifed and no current default defined.");
+ env.failure("No port specified and no current default defined.");
}
} else {
portName = t.nextToken();
diff --git a/jdk/src/share/classes/com/sun/tools/script/shell/init.js b/jdk/src/share/classes/com/sun/tools/script/shell/init.js
index ae2cdc42d95..ced3ba06367 100644
--- a/jdk/src/share/classes/com/sun/tools/script/shell/init.js
+++ b/jdk/src/share/classes/com/sun/tools/script/shell/init.js
@@ -806,7 +806,7 @@ function XSLTransform(inp, style, out) {
out = arguments[2];
break;
default:
- println("XSL tranform requires 2 or 3 arguments");
+ println("XSL transform requires 2 or 3 arguments");
return;
}
diff --git a/jdk/src/share/classes/com/sun/tools/script/shell/messages.properties b/jdk/src/share/classes/com/sun/tools/script/shell/messages.properties
index 9caf20efd41..4494f73b73b 100644
--- a/jdk/src/share/classes/com/sun/tools/script/shell/messages.properties
+++ b/jdk/src/share/classes/com/sun/tools/script/shell/messages.properties
@@ -36,7 +36,7 @@ engine.not.found=\
script engine for language {0} can not be found
engine.info=\
- Language {0} {1} implemention "{2}" {3}
+ Language {0} {1} implementation "{2}" {3}
encoding.unsupported=\
encoding {0} is not supported
diff --git a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java
index 0afd70f9423..60916ed938b 100644
--- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java
+++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java
@@ -360,7 +360,7 @@ public class RequiredModelMBean
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),
"setManagedResource(Object,String)",
- "Managed Resouce Type is not supported: " + mr_type);
+ "Managed Resource Type is not supported: " + mr_type);
}
throw new InvalidTargetObjectTypeException(mr_type);
}
@@ -369,7 +369,7 @@ public class RequiredModelMBean
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),
"setManagedResource(Object,String)",
- "Managed Resouce is valid");
+ "Managed Resource is valid");
}
managedResource = mr;
diff --git a/jdk/src/share/classes/javax/swing/KeyboardManager.java b/jdk/src/share/classes/javax/swing/KeyboardManager.java
index 3ce79226a5f..afbd93e734e 100644
--- a/jdk/src/share/classes/javax/swing/KeyboardManager.java
+++ b/jdk/src/share/classes/javax/swing/KeyboardManager.java
@@ -208,7 +208,7 @@ class KeyboardManager {
public boolean fireKeyboardAction(KeyEvent e, boolean pressed, Container topAncestor) {
if (e.isConsumed()) {
- System.out.println("Aquired pre-used event!");
+ System.out.println("Acquired pre-used event!");
Thread.dumpStack();
}
diff --git a/jdk/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java b/jdk/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java
index cbdfc015a19..45b3766c33e 100644
--- a/jdk/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java
+++ b/jdk/src/share/classes/javax/swing/SortingFocusTraversalPolicy.java
@@ -116,7 +116,7 @@ public class SortingFocusTraversalPolicy
index = Collections.binarySearch(cycle, aComponent, comparator);
} catch (ClassCastException e) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
- log.fine("### During the binary search for " + aComponent + " the exception occured: ", e);
+ log.fine("### During the binary search for " + aComponent + " the exception occurred: ", e);
}
return -1;
}
diff --git a/jdk/src/share/classes/javax/swing/text/AbstractDocument.java b/jdk/src/share/classes/javax/swing/text/AbstractDocument.java
index 5ccd80d95e5..71e9d5d8c60 100644
--- a/jdk/src/share/classes/javax/swing/text/AbstractDocument.java
+++ b/jdk/src/share/classes/javax/swing/text/AbstractDocument.java
@@ -1367,7 +1367,7 @@ public abstract class AbstractDocument implements Document, Serializable {
currWriter = Thread.currentThread();
numWriters = 1;
} catch (InterruptedException e) {
- throw new Error("Interrupted attempt to aquire write lock");
+ throw new Error("Interrupted attempt to acquire write lock");
}
}
@@ -1409,7 +1409,7 @@ public abstract class AbstractDocument implements Document, Serializable {
}
numReaders += 1;
} catch (InterruptedException e) {
- throw new Error("Interrupted attempt to aquire read lock");
+ throw new Error("Interrupted attempt to acquire read lock");
}
}
diff --git a/jdk/src/share/classes/sun/awt/AppContext.java b/jdk/src/share/classes/sun/awt/AppContext.java
index e0f232e5c0c..b7bfc8072c2 100644
--- a/jdk/src/share/classes/sun/awt/AppContext.java
+++ b/jdk/src/share/classes/sun/awt/AppContext.java
@@ -430,7 +430,7 @@ public final class AppContext {
try {
w.dispose();
} catch (Throwable t) {
- log.finer("exception occured while disposing app context", t);
+ log.finer("exception occurred while disposing app context", t);
}
}
AccessController.doPrivileged(new PrivilegedAction() {
diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java
index 37837b24db9..3a70921c109 100644
--- a/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java
+++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/JVM_MANAGEMENT_MIB_IMPL.java
@@ -188,7 +188,7 @@ public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB {
sendTrap(trap, list);
}catch(Exception e) {
log.error("handleNotification",
- "Exception occured : " + e);
+ "Exception occurred : " + e);
}
}
}
@@ -243,7 +243,7 @@ public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB {
adaptor.snmpV2Trap(peer, trap, list, null);
}catch(Exception e) {
log.error("sendTrap",
- "Exception occured while sending trap to [" +
+ "Exception occurred while sending trap to [" +
target + "]. Exception : " + e);
log.debug("sendTrap",e);
}
diff --git a/jdk/src/share/classes/sun/misc/ExtensionDependency.java b/jdk/src/share/classes/sun/misc/ExtensionDependency.java
index 86f4308c9c3..f09b3ac117e 100644
--- a/jdk/src/share/classes/sun/misc/ExtensionDependency.java
+++ b/jdk/src/share/classes/sun/misc/ExtensionDependency.java
@@ -265,7 +265,7 @@ public class ExtensionDependency {
* the jar file.
*
*
- * @param extensionName key in the attibute list
+ * @param extensionName key in the attribute list
* @param attr manifest file attributes
* @param file installed extension jar file to compare the requested
* extension against.
diff --git a/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java b/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java
index a9649c7fca9..6b997e42647 100644
--- a/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java
+++ b/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java
@@ -1132,7 +1132,7 @@ public class RMIGenerator implements RMIConstants, Generator {
throws IOException
{
if (types.length != names.length) {
- throw new Error("paramter type and name arrays different sizes");
+ throw new Error("parameter type and name arrays different sizes");
}
for (int i = 0; i < types.length; i++) {
@@ -1213,7 +1213,7 @@ public class RMIGenerator implements RMIConstants, Generator {
throws IOException
{
if (types.length != names.length) {
- throw new Error("paramter type and name arrays different sizes");
+ throw new Error("parameter type and name arrays different sizes");
}
boolean readObject = false;
diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java b/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java
index c15ddd23529..7b34ff83914 100644
--- a/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitialToken.java
@@ -192,7 +192,7 @@ abstract class InitialToken extends Krb5Token {
if (krbCredMessage.length > 0x0000ffff)
throw new GSSException(GSSException.FAILURE, -1,
- "Incorrect messsage length");
+ "Incorrect message length");
writeLittleEndian(krbCredMessage.length, temp);
checksumBytes[pos++] = temp[0];
diff --git a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
index 0312a1fbf76..1acc3a9a06b 100644
--- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
@@ -360,7 +360,7 @@ public class SpNegoContext implements GSSContextSpi {
if (internal_mech == null) {
// return wth failure
throw new GSSException(errorCode, -1,
- "supported mechansim from server is null");
+ "supported mechanism from server is null");
}
// get the negotiated result
@@ -911,7 +911,7 @@ public class SpNegoContext implements GSSContextSpi {
return mechContext.isEstablished();
} else {
if (DEBUG) {
- System.out.println("The underlying mechansim context has " +
+ System.out.println("The underlying mechanism context has " +
"not been initialized");
}
return false;
@@ -1024,7 +1024,7 @@ public class SpNegoContext implements GSSContextSpi {
return peerName;
} else {
if (DEBUG) {
- System.out.println("The underlying mechansim context has " +
+ System.out.println("The underlying mechanism context has " +
"not been initialized");
}
return null;
@@ -1040,7 +1040,7 @@ public class SpNegoContext implements GSSContextSpi {
return myName;
} else {
if (DEBUG) {
- System.out.println("The underlying mechansim context has " +
+ System.out.println("The underlying mechanism context has " +
"not been initialized");
}
return null;
diff --git a/jdk/src/share/demo/jfc/FileChooserDemo/FileChooserDemo.java b/jdk/src/share/demo/jfc/FileChooserDemo/FileChooserDemo.java
index e492e09e032..24c5533f9a1 100644
--- a/jdk/src/share/demo/jfc/FileChooserDemo/FileChooserDemo.java
+++ b/jdk/src/share/demo/jfc/FileChooserDemo/FileChooserDemo.java
@@ -450,9 +450,9 @@ public class FileChooserDemo extends JPanel implements ActionListener {
"User cancelled operation. No file was chosen.");
} else if (retval == ERROR_OPTION) {
JOptionPane.showMessageDialog(frame,
- "An error occured. No file was chosen.");
+ "An error occurred. No file was chosen.");
} else {
- JOptionPane.showMessageDialog(frame, "Unknown operation occured.");
+ JOptionPane.showMessageDialog(frame, "Unknown operation occurred.");
}
}
diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c
index 8889f740d0e..79d5250390d 100644
--- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c
+++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c
@@ -598,16 +598,16 @@ void jAttributeArrayToCKAttributeArray(JNIEnv *env, jobjectArray jArray, CK_ATTR
throwOutOfMemoryError(env, 0);
return;
}
- TRACE1(", converting %d attibutes", jLength);
+ TRACE1(", converting %d attributes", jLength);
for (i=0; i<(*ckpLength); i++) {
- TRACE1(", getting %d. attibute", i);
+ TRACE1(", getting %d. attribute", i);
jAttribute = (*env)->GetObjectArrayElement(env, jArray, i);
if ((*env)->ExceptionCheck(env)) {
freeCKAttributeArray(*ckpArray, i);
return;
}
TRACE1(", jAttribute = %d", jAttribute);
- TRACE1(", converting %d. attibute", i);
+ TRACE1(", converting %d. attribute", i);
(*ckpArray)[i] = jAttributeToCKAttribute(env, jAttribute);
if ((*env)->ExceptionCheck(env)) {
freeCKAttributeArray(*ckpArray, i);
diff --git a/jdk/src/share/sample/nio/chatserver/ClientReader.java b/jdk/src/share/sample/nio/chatserver/ClientReader.java
index de7f639e81b..822125a946c 100644
--- a/jdk/src/share/sample/nio/chatserver/ClientReader.java
+++ b/jdk/src/share/sample/nio/chatserver/ClientReader.java
@@ -58,7 +58,7 @@ class ClientReader {
}
/**
- * Runs a cycle of doing a beforeRead action and then inquiring a new
+ * Runs a cycle of doing a beforeRead action and then enqueuing a new
* read on the client. Handles closed channels and errors while reading.
* If the client is still connected a new round of actions are called.
*/
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
index e61273dc4d4..912a951f374 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
@@ -1173,7 +1173,7 @@ abstract class XDecoratedPeer extends XWindowPeer {
}
if (target == activeWindow && target != focusedWindow) {
// Happens when an owned window is currently focused
- focusLog.fine("Focus is on child window - transfering it back to the owner");
+ focusLog.fine("Focus is on child window - transferring it back to the owner");
handleWindowFocusInSync(-1);
return true;
}
diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
index 725e66f8bec..d84712ba97c 100644
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
@@ -266,7 +266,7 @@ final class WindowsSelectorImpl extends SelectorImpl {
private void checkForException() throws IOException {
if (exception == null)
return;
- StringBuffer message = new StringBuffer("An exception occured" +
+ StringBuffer message = new StringBuffer("An exception occurred" +
" during the execution of select(): \n");
message.append(exception);
message.append('\n');
diff --git a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java
index ce0e3e7fb5d..566b0bee12c 100644
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Klist.java
@@ -336,7 +336,7 @@ public class Klist {
System.out.println(" name\t name of credentials cache or " +
" keytab with the prefix. File-based cache or "
+ "keytab's prefix is FILE:.");
- System.out.println(" -c specifes that credential cache is to be " +
+ System.out.println(" -c specifies that credential cache is to be " +
"listed");
System.out.println(" -k specifies that key tab is to be listed");
System.out.println(" options for credentials caches:");
diff --git a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java
index eeeb848e6e5..bf09016136f 100644
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Ktab.java
@@ -381,12 +381,12 @@ public class Ktab {
}
}
} catch (KrbException e) {
- System.err.println("Error occured while deleting the entry. "+
+ System.err.println("Error occurred while deleting the entry. "+
"Deletion failed.");
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
- System.err.println("Error occured while deleting the entry. "+
+ System.err.println("Error occurred while deleting the entry. "+
" Deletion failed.");
e.printStackTrace();
System.exit(-1);
From f7db4eb56b4c34653120d684d0aabd96b9af18ab Mon Sep 17 00:00:00 2001
From: Dan Xu
Date: Fri, 1 Nov 2013 14:40:03 -0700
Subject: [PATCH 009/110] 8027624:
com/sun/crypto/provider/KeyFactory/TestProviderLeak.java unstable again
Reviewed-by: wetmore
---
.../crypto/provider/KeyFactory/TestProviderLeak.java | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java
index 04fa96a9813..83b2c690410 100644
--- a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java
+++ b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6578538
+ * @bug 6578538 8027624
* @summary com.sun.crypto.provider.SunJCE instance leak using KRB5 and
* LoginContext
* @author Brad Wetmore
@@ -89,10 +89,6 @@ public class TestProviderLeak {
}
public static void main(String [] args) throws Exception {
- // Eat up memory
- Deque dummyData = eatupMemory();
- assert (dummyData != null);
-
// Prepare the test
final SecretKeyFactory skf =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "SunJCE");
@@ -107,6 +103,10 @@ public class TestProviderLeak {
}
};
+ // Eat up memory
+ Deque dummyData = eatupMemory();
+ assert (dummyData != null);
+
// Start testing iteration
try {
for (int i = 0; i <= 1000; i++) {
From bb01d169de996d6a374930671d0293cdfb2a4567 Mon Sep 17 00:00:00 2001
From: Sergey Kuksenko
Date: Sat, 2 Nov 2013 20:08:10 -0700
Subject: [PATCH 010/110] 8024635: Caching MethodType's descriptor string
improves lambda linkage performance
Better interpreted and compiled performance of operations in MethodType important to LambdaMetafactory.
Reviewed-by: jrose, twisti, mchung
---
.../classes/java/lang/invoke/MethodType.java | 51 ++++++++++++-------
1 file changed, 33 insertions(+), 18 deletions(-)
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodType.java b/jdk/src/share/classes/java/lang/invoke/MethodType.java
index f8e0967c7af..781ecfc56bd 100644
--- a/jdk/src/share/classes/java/lang/invoke/MethodType.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java
@@ -32,6 +32,7 @@ import java.lang.ref.ReferenceQueue;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import sun.invoke.util.BytecodeDescriptor;
@@ -98,13 +99,25 @@ class MethodType implements java.io.Serializable {
private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version
private @Stable Invokers invokers; // cache of handy higher-order adapters
+ private @Stable String methodDescriptor; // cache for toMethodDescriptorString
/**
* Check the given parameters for validity and store them into the final fields.
*/
- private MethodType(Class> rtype, Class>[] ptypes) {
+ private MethodType(Class> rtype, Class>[] ptypes, boolean trusted) {
checkRtype(rtype);
checkPtypes(ptypes);
+ this.rtype = rtype;
+ // defensively copy the array passed in by the user
+ this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
+ }
+
+ /**
+ * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table.
+ * Does not check the given parameters for validity, and must be discarded after it is used as a searching key.
+ * The parameters are reversed for this constructor, so that is is not accidentally used.
+ */
+ private MethodType(Class>[] ptypes, Class> rtype) {
this.rtype = rtype;
this.ptypes = ptypes;
}
@@ -146,20 +159,21 @@ class MethodType implements java.io.Serializable {
/*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker
private static void checkRtype(Class> rtype) {
- rtype.equals(rtype); // null check
+ Objects.requireNonNull(rtype);
}
- private static int checkPtype(Class> ptype) {
- ptype.getClass(); //NPE
+ private static void checkPtype(Class> ptype) {
+ Objects.requireNonNull(ptype);
if (ptype == void.class)
throw newIllegalArgumentException("parameter type cannot be void");
- if (ptype == double.class || ptype == long.class) return 1;
- return 0;
}
/** Return number of extra slots (count of long/double args). */
private static int checkPtypes(Class>[] ptypes) {
int slots = 0;
for (Class> ptype : ptypes) {
- slots += checkPtype(ptype);
+ checkPtype(ptype);
+ if (ptype == double.class || ptype == long.class) {
+ slots++;
+ }
}
checkSlotCount(ptypes.length + slots);
return slots;
@@ -284,20 +298,16 @@ class MethodType implements java.io.Serializable {
*/
/*trusted*/ static
MethodType makeImpl(Class> rtype, Class>[] ptypes, boolean trusted) {
+ MethodType mt = internTable.get(new MethodType(ptypes, rtype));
+ if (mt != null)
+ return mt;
if (ptypes.length == 0) {
ptypes = NO_PTYPES; trusted = true;
}
- MethodType mt1 = new MethodType(rtype, ptypes);
- MethodType mt0 = internTable.get(mt1);
- if (mt0 != null)
- return mt0;
- if (!trusted)
- // defensively copy the array passed in by the user
- mt1 = new MethodType(rtype, ptypes.clone());
+ mt = new MethodType(rtype, ptypes, trusted);
// promote the object to the Real Thing, and reprobe
- MethodTypeForm form = MethodTypeForm.findForm(mt1);
- mt1.form = form;
- return internTable.add(mt1);
+ mt.form = MethodTypeForm.findForm(mt);
+ return internTable.add(mt);
}
private static final MethodType[] objectOnlyTypes = new MethodType[20];
@@ -919,7 +929,12 @@ class MethodType implements java.io.Serializable {
* @return the bytecode type descriptor representation
*/
public String toMethodDescriptorString() {
- return BytecodeDescriptor.unparse(this);
+ String desc = methodDescriptor;
+ if (desc == null) {
+ desc = BytecodeDescriptor.unparse(this);
+ methodDescriptor = desc;
+ }
+ return desc;
}
/*non-public*/ static String toFieldDescriptorString(Class> cls) {
From bd40c9b63dbc83449356a4f7f50bb6f20f27a2ff Mon Sep 17 00:00:00 2001
From: Tristan Yan
Date: Mon, 4 Nov 2013 06:58:30 -0500
Subject: [PATCH 011/110] 8025198: Intermittent test failure:
java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
Reviewed-by: martin, dholmes
---
jdk/makefiles/CompileLaunchers.gmk | 2 +-
jdk/makefiles/lib/CoreLibraries.gmk | 2 +-
jdk/src/share/bin/java.c | 54 +++++++++++++++----
.../ThreadPoolExecutor/ThrowingTasks.java | 16 +++++-
4 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk
index af5b3583758..2de3900acd0 100644
--- a/jdk/makefiles/CompileLaunchers.gmk
+++ b/jdk/makefiles/CompileLaunchers.gmk
@@ -154,7 +154,7 @@ define SetupLauncher
$(ORIGIN_ARG) \
$$($1_LDFLAGS), \
LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \
- LDFLAGS_linux := -lpthread \
+ LDFLAGS_linux := -lpthread -lrt \
$(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
$(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
diff --git a/jdk/makefiles/lib/CoreLibraries.gmk b/jdk/makefiles/lib/CoreLibraries.gmk
index 29c1d5fc08a..a631cf80cde 100644
--- a/jdk/makefiles/lib/CoreLibraries.gmk
+++ b/jdk/makefiles/lib/CoreLibraries.gmk
@@ -414,7 +414,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
LDFLAGS_macosx := -framework Cocoa -framework Security -framework ApplicationServices, \
LDFLAGS_SUFFIX_solaris := $(LIBZ) $(LIBDL) -lc, \
- LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread, \
+ LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread -lrt, \
LDFLAGS_SUFFIX_macosx := $(LIBZ), \
LDFLAGS_SUFFIX_windows := \
-export:JLI_Launch \
diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c
index 73c532676b3..9d1b2bf0209 100644
--- a/jdk/src/share/bin/java.c
+++ b/jdk/src/share/bin/java.c
@@ -53,6 +53,8 @@
#include "java.h"
+#include
+
/*
* A NOTE TO DEVELOPERS: For performance reasons it is important that
* the program image remain relatively small until after SelectVersion
@@ -167,6 +169,26 @@ static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong maxHeapSize = 0; /* max heap size */
static jlong initialHeapSize = 0; /* inital heap size */
+static jlong timestamps[256];
+static char* descriptors[256];
+static int ts_index = 0;
+
+static void stamp(char* info) {
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ timestamps[ts_index] = ((jlong)tp.tv_sec) * (1000 * 1000 * 1000) + tp.tv_nsec;
+ descriptors[ts_index++] = info;
+}
+
+static void report_times() {
+ printf("[0] %s\n", descriptors[0]);
+ int i;
+ for (i = 1; i < ts_index; i++) {
+ jlong elapsed = timestamps[i] - timestamps[i-1];
+ printf("[%d] elapsed us: %.3g - Next: %s\n", i, (elapsed/1000.0), descriptors[i]);
+ }
+}
+
/*
* Entry point.
*/
@@ -184,6 +206,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
jint ergo /* ergonomics class policy */
)
{
+ stamp("Entered JLI_Launch");
int mode = LM_UNKNOWN;
char *what = NULL;
char *cpath = 0;
@@ -203,6 +226,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
_wc_enabled = cpwildcard;
_ergo_policy = ergo;
+stamp("InitLauncher");
InitLauncher(javaw);
DumpState();
if (JLI_IsTraceLauncher()) {
@@ -231,8 +255,9 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
* (Note: This side effect has been disabled. See comment on
* bugid 5030265 below.)
*/
+stamp("SelectVersion");
SelectVersion(argc, argv, &main_class);
-
+stamp("CreateExecutionEnvironment");
CreateExecutionEnvironment(&argc, &argv,
jrepath, sizeof(jrepath),
jvmpath, sizeof(jvmpath),
@@ -244,11 +269,11 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
if (JLI_IsTraceLauncher()) {
start = CounterGet();
}
-
+stamp("LoadJavaVM");
if (!LoadJavaVM(jvmpath, &ifn)) {
return(6);
}
-
+stamp("Arg processing");
if (JLI_IsTraceLauncher()) {
end = CounterGet();
}
@@ -295,8 +320,10 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
/* set the -Dsun.java.launcher.* platform properties */
SetJavaLauncherPlatformProps();
-
- return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
+stamp("JVMInit");
+ int res = JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
+stamp("initial thread DONE");
+ return res;
}
/*
* Always detach the main thread so that it appears to have ended when
@@ -348,6 +375,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
int JNICALL
JavaMain(void * _args)
{
+stamp("JavaMain");
JavaMainArgs *args = (JavaMainArgs *)_args;
int argc = args->argc;
char **argv = args->argv;
@@ -363,11 +391,12 @@ JavaMain(void * _args)
jobjectArray mainArgs;
int ret = 0;
jlong start, end;
-
+stamp("RegisterThread");
RegisterThread();
/* Initialize the virtual machine */
start = CounterGet();
+stamp("InitializeJVM");
if (!InitializeJVM(&vm, &env, &ifn)) {
JLI_ReportErrorMessage(JVM_ERROR1);
exit(1);
@@ -436,6 +465,7 @@ JavaMain(void * _args)
* This method also correctly handles launching existing JavaFX
* applications that may or may not have a Main-Class manifest entry.
*/
+stamp("LoadMainClass");
mainClass = LoadMainClass(env, mode, what);
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
/*
@@ -444,6 +474,7 @@ JavaMain(void * _args)
* applications own main class but rather a helper class. To keep things
* consistent in the UI we need to track and report the application main class.
*/
+stamp("GetApplicationClass");
appClass = GetApplicationClass(env);
NULL_CHECK_RETURN_VALUE(appClass, -1);
/*
@@ -453,6 +484,7 @@ JavaMain(void * _args)
* instead of mainClass as that may be a launcher or helper class instead
* of the application class.
*/
+stamp("PostJVMInit");
PostJVMInit(env, appClass, vm);
/*
* The LoadMainClass not only loads the main class, it will also ensure
@@ -460,17 +492,20 @@ JavaMain(void * _args)
* is not required. The main method is invoked here so that extraneous java
* stacks are not in the application stack trace.
*/
+stamp("Get main method");
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
-
+stamp("CreateApplicationArgs");
/* Build platform specific argument array */
mainArgs = CreateApplicationArgs(env, argv, argc);
CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
/* Invoke main method. */
+stamp("Invoke main method");
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
-
+stamp("main complete");
+report_times();
/*
* The launcher's exit code (in the absence of calls to
* System.exit) will be non-zero if main threw an exception.
@@ -1875,6 +1910,7 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char **argv,
int mode, char *what, int ret)
{
+stamp("ContinueInNewThread");
/*
* If user doesn't specify stack size, check if VM has a preference.
@@ -1900,7 +1936,7 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize,
args.mode = mode;
args.what = what;
args.ifn = *ifn;
-
+stamp("ContinueInNewThread0");
rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
/* If the caller has deemed there is an error we
* simply return that, otherwise we return the value of
diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
index 1394a4c38ed..47c28540f24 100644
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
@@ -33,6 +33,7 @@ import java.security.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.ReentrantLock;
public class ThrowingTasks {
static final Random rnd = new Random();
@@ -156,6 +157,7 @@ public class ThrowingTasks {
}
static class CheckingExecutor extends ThreadPoolExecutor {
+ private final ReentrantLock lock = new ReentrantLock();
CheckingExecutor() {
super(10, 10,
1L, TimeUnit.HOURS,
@@ -163,10 +165,20 @@ public class ThrowingTasks {
tf);
}
@Override protected void beforeExecute(Thread t, Runnable r) {
- allStarted.countDown();
- if (allStarted.getCount() < getCorePoolSize())
+ final boolean lessThanCorePoolSize;
+ // Add a lock to sync allStarted.countDown() and
+ // allStarted.getCount() < getCorePoolSize()
+ lock.lock();
+ try {
+ allStarted.countDown();
+ lessThanCorePoolSize = allStarted.getCount() < getCorePoolSize();
+ } finally {
+ lock.unlock();
+ }
+ if (lessThanCorePoolSize) {
try { allContinue.await(); }
catch (InterruptedException x) { unexpected(x); }
+ }
beforeExecuteCount.getAndIncrement();
check(! isTerminated());
((Flaky)r).beforeExecute.run();
From c43c119a472b40b5a990a7e2135b3cfb637c6ab4 Mon Sep 17 00:00:00 2001
From: David Holmes
Date: Mon, 4 Nov 2013 07:39:48 -0500
Subject: [PATCH 012/110] 8027755: Anti-delta incorrect push for 8025198
Reviewed-by: alanb
---
jdk/makefiles/CompileLaunchers.gmk | 2 +-
jdk/makefiles/lib/CoreLibraries.gmk | 2 +-
jdk/src/share/bin/java.c | 54 +++++------------------------
3 files changed, 11 insertions(+), 47 deletions(-)
diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk
index 2de3900acd0..af5b3583758 100644
--- a/jdk/makefiles/CompileLaunchers.gmk
+++ b/jdk/makefiles/CompileLaunchers.gmk
@@ -154,7 +154,7 @@ define SetupLauncher
$(ORIGIN_ARG) \
$$($1_LDFLAGS), \
LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \
- LDFLAGS_linux := -lpthread -lrt \
+ LDFLAGS_linux := -lpthread \
$(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
$(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
diff --git a/jdk/makefiles/lib/CoreLibraries.gmk b/jdk/makefiles/lib/CoreLibraries.gmk
index a631cf80cde..29c1d5fc08a 100644
--- a/jdk/makefiles/lib/CoreLibraries.gmk
+++ b/jdk/makefiles/lib/CoreLibraries.gmk
@@ -414,7 +414,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
LDFLAGS_macosx := -framework Cocoa -framework Security -framework ApplicationServices, \
LDFLAGS_SUFFIX_solaris := $(LIBZ) $(LIBDL) -lc, \
- LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread -lrt, \
+ LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread, \
LDFLAGS_SUFFIX_macosx := $(LIBZ), \
LDFLAGS_SUFFIX_windows := \
-export:JLI_Launch \
diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c
index 9d1b2bf0209..73c532676b3 100644
--- a/jdk/src/share/bin/java.c
+++ b/jdk/src/share/bin/java.c
@@ -53,8 +53,6 @@
#include "java.h"
-#include
-
/*
* A NOTE TO DEVELOPERS: For performance reasons it is important that
* the program image remain relatively small until after SelectVersion
@@ -169,26 +167,6 @@ static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong maxHeapSize = 0; /* max heap size */
static jlong initialHeapSize = 0; /* inital heap size */
-static jlong timestamps[256];
-static char* descriptors[256];
-static int ts_index = 0;
-
-static void stamp(char* info) {
- struct timespec tp;
- clock_gettime(CLOCK_MONOTONIC, &tp);
- timestamps[ts_index] = ((jlong)tp.tv_sec) * (1000 * 1000 * 1000) + tp.tv_nsec;
- descriptors[ts_index++] = info;
-}
-
-static void report_times() {
- printf("[0] %s\n", descriptors[0]);
- int i;
- for (i = 1; i < ts_index; i++) {
- jlong elapsed = timestamps[i] - timestamps[i-1];
- printf("[%d] elapsed us: %.3g - Next: %s\n", i, (elapsed/1000.0), descriptors[i]);
- }
-}
-
/*
* Entry point.
*/
@@ -206,7 +184,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
jint ergo /* ergonomics class policy */
)
{
- stamp("Entered JLI_Launch");
int mode = LM_UNKNOWN;
char *what = NULL;
char *cpath = 0;
@@ -226,7 +203,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
_wc_enabled = cpwildcard;
_ergo_policy = ergo;
-stamp("InitLauncher");
InitLauncher(javaw);
DumpState();
if (JLI_IsTraceLauncher()) {
@@ -255,9 +231,8 @@ stamp("InitLauncher");
* (Note: This side effect has been disabled. See comment on
* bugid 5030265 below.)
*/
-stamp("SelectVersion");
SelectVersion(argc, argv, &main_class);
-stamp("CreateExecutionEnvironment");
+
CreateExecutionEnvironment(&argc, &argv,
jrepath, sizeof(jrepath),
jvmpath, sizeof(jvmpath),
@@ -269,11 +244,11 @@ stamp("CreateExecutionEnvironment");
if (JLI_IsTraceLauncher()) {
start = CounterGet();
}
-stamp("LoadJavaVM");
+
if (!LoadJavaVM(jvmpath, &ifn)) {
return(6);
}
-stamp("Arg processing");
+
if (JLI_IsTraceLauncher()) {
end = CounterGet();
}
@@ -320,10 +295,8 @@ stamp("Arg processing");
/* set the -Dsun.java.launcher.* platform properties */
SetJavaLauncherPlatformProps();
-stamp("JVMInit");
- int res = JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
-stamp("initial thread DONE");
- return res;
+
+ return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
}
/*
* Always detach the main thread so that it appears to have ended when
@@ -375,7 +348,6 @@ stamp("initial thread DONE");
int JNICALL
JavaMain(void * _args)
{
-stamp("JavaMain");
JavaMainArgs *args = (JavaMainArgs *)_args;
int argc = args->argc;
char **argv = args->argv;
@@ -391,12 +363,11 @@ stamp("JavaMain");
jobjectArray mainArgs;
int ret = 0;
jlong start, end;
-stamp("RegisterThread");
+
RegisterThread();
/* Initialize the virtual machine */
start = CounterGet();
-stamp("InitializeJVM");
if (!InitializeJVM(&vm, &env, &ifn)) {
JLI_ReportErrorMessage(JVM_ERROR1);
exit(1);
@@ -465,7 +436,6 @@ stamp("InitializeJVM");
* This method also correctly handles launching existing JavaFX
* applications that may or may not have a Main-Class manifest entry.
*/
-stamp("LoadMainClass");
mainClass = LoadMainClass(env, mode, what);
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
/*
@@ -474,7 +444,6 @@ stamp("LoadMainClass");
* applications own main class but rather a helper class. To keep things
* consistent in the UI we need to track and report the application main class.
*/
-stamp("GetApplicationClass");
appClass = GetApplicationClass(env);
NULL_CHECK_RETURN_VALUE(appClass, -1);
/*
@@ -484,7 +453,6 @@ stamp("GetApplicationClass");
* instead of mainClass as that may be a launcher or helper class instead
* of the application class.
*/
-stamp("PostJVMInit");
PostJVMInit(env, appClass, vm);
/*
* The LoadMainClass not only loads the main class, it will also ensure
@@ -492,20 +460,17 @@ stamp("PostJVMInit");
* is not required. The main method is invoked here so that extraneous java
* stacks are not in the application stack trace.
*/
-stamp("Get main method");
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
CHECK_EXCEPTION_NULL_LEAVE(mainID);
-stamp("CreateApplicationArgs");
+
/* Build platform specific argument array */
mainArgs = CreateApplicationArgs(env, argv, argc);
CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
/* Invoke main method. */
-stamp("Invoke main method");
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
-stamp("main complete");
-report_times();
+
/*
* The launcher's exit code (in the absence of calls to
* System.exit) will be non-zero if main threw an exception.
@@ -1910,7 +1875,6 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char **argv,
int mode, char *what, int ret)
{
-stamp("ContinueInNewThread");
/*
* If user doesn't specify stack size, check if VM has a preference.
@@ -1936,7 +1900,7 @@ stamp("ContinueInNewThread");
args.mode = mode;
args.what = what;
args.ifn = *ifn;
-stamp("ContinueInNewThread0");
+
rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
/* If the caller has deemed there is an error we
* simply return that, otherwise we return the value of
From 8c97f82aae76084c8c6f1d57ef56605907caa296 Mon Sep 17 00:00:00 2001
From: Brian Burkhalter
Date: Mon, 4 Nov 2013 08:05:02 -0800
Subject: [PATCH 013/110] 8027625:
test/java/math/BigInteger/ExtremeShiftingTests.java needs @run tag to specify
heap size
Add @run tag to specify heap size
Reviewed-by: alanb, dxu
---
jdk/test/java/math/BigInteger/ExtremeShiftingTests.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java b/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java
index 4c39a6097fd..5ddc07e887c 100644
--- a/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java
+++ b/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java
@@ -25,6 +25,7 @@
* @test
* @bug 6371401
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
+ * @run main/othervm -Xmx512m ExtremeShiftingTests
* @author Joseph D. Darcy
*/
import java.math.BigInteger;
From 2d8325d24451e286631d2d2fbcd2696756ebc924 Mon Sep 17 00:00:00 2001
From: Michael McMahon
Date: Mon, 4 Nov 2013 17:47:59 +0000
Subject: [PATCH 014/110] 8027687: The constructors of URLPermission class do
not behave as described in javad
Reviewed-by: chegar, mduigou
---
.../share/classes/java/net/HostPortrange.java | 36 +++++++++++++++++--
.../share/classes/java/net/URLPermission.java | 5 ++-
.../net/URLPermission/URLPermissionTest.java | 13 ++++++-
3 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/jdk/src/share/classes/java/net/HostPortrange.java b/jdk/src/share/classes/java/net/HostPortrange.java
index fc5e3d98a20..3c924d8bfc0 100644
--- a/jdk/src/share/classes/java/net/HostPortrange.java
+++ b/jdk/src/share/classes/java/net/HostPortrange.java
@@ -114,7 +114,7 @@ class HostPortrange {
if (hoststr.equals("*")) {
hoststr = "";
} else if (hoststr.startsWith("*.")) {
- hoststr = hoststr.substring(1).toLowerCase(); // leave the '.' ?
+ hoststr = toLowerCase(hoststr.substring(1));
} else {
throw new IllegalArgumentException("invalid host wildcard specification");
}
@@ -147,7 +147,7 @@ class HostPortrange {
hoststr = sb.toString();
} else {
// regular domain name
- hoststr = hoststr.toLowerCase();
+ hoststr = toLowerCase(hoststr);
}
}
}
@@ -161,6 +161,38 @@ class HostPortrange {
}
}
+ static final int CASE_DIFF = 'A' - 'a';
+
+ /**
+ * Convert to lower case, and check that all chars are ascii
+ * alphanumeric, '-' or '.' only.
+ */
+ static String toLowerCase(String s) {
+ int len = s.length();
+ StringBuilder sb = null;
+
+ for (int i=0; i= 'a' && c <= 'z') || (c == '.')) {
+ if (sb != null)
+ sb.append(c);
+ } else if ((c >= '0' && c <= '9') || (c == '-')) {
+ if (sb != null)
+ sb.append(c);
+ } else if (c >= 'A' && c <= 'Z') {
+ if (sb == null) {
+ sb = new StringBuilder(len);
+ sb.append(s, 0, i);
+ }
+ sb.append((char)(c - CASE_DIFF));
+ } else {
+ throw new IllegalArgumentException("Invalid characters in hostname");
+ }
+ }
+ return sb == null ? s : sb.toString();
+ }
+
+
public boolean literal() {
return literal;
}
diff --git a/jdk/src/share/classes/java/net/URLPermission.java b/jdk/src/share/classes/java/net/URLPermission.java
index 7ad56a1c20f..13472a9e5ab 100644
--- a/jdk/src/share/classes/java/net/URLPermission.java
+++ b/jdk/src/share/classes/java/net/URLPermission.java
@@ -426,7 +426,10 @@ public final class URLPermission extends Permission {
this.ssp = url.substring(delim + 1);
if (!ssp.startsWith("//")) {
- this.authority = new Authority(scheme, ssp.toLowerCase());
+ if (!ssp.equals("*")) {
+ throw new IllegalArgumentException("invalid URL string");
+ }
+ this.authority = new Authority(scheme, "*");
return;
}
String authpath = ssp.substring(2);
diff --git a/jdk/test/java/net/URLPermission/URLPermissionTest.java b/jdk/test/java/net/URLPermission/URLPermissionTest.java
index 3bf862b6dc9..948e9dabb13 100644
--- a/jdk/test/java/net/URLPermission/URLPermissionTest.java
+++ b/jdk/test/java/net/URLPermission/URLPermissionTest.java
@@ -186,6 +186,14 @@ public class URLPermissionTest {
imtest("http:*", "https://www.foo.com/a/b/c", false),
imtest("http:*", "http://www.foo.com/a/b/c", true),
imtest("http:*", "http://foo/bar", true),
+ imtest("http://WWW.foO.cOM/a/b/*", "http://wwW.foo.com/a/b/c", true),
+ imtest("http://wWw.fOo.cOm/a/b/*", "http://Www.foo.com/a/b/*", true),
+ imtest("http://www.FOO.com/", "http://www.foo.COM/", true),
+ imtest("http://66ww-w.F-O012O.com/", "http://66ww-w.f-o012o.COM/",true),
+ imtest("http://xn--ire-9la.com/", "http://xn--ire-9la.COM/", true),
+ imtest("http://x/", "http://X/", true),
+ imtest("http://x/", "http://x/", true),
+ imtest("http://X/", "http://X/", true),
imtest("http://foo/bar", "https://foo/bar", false)
};
@@ -194,9 +202,12 @@ public class URLPermissionTest {
static Test[] exceptionTests = {
extest("http://1.2.3.4.5/a/b/c"),
extest("http://www.*.com"),
- //extest("http://www.foo.com:1-X"),
extest("http://[foo.com]:99"),
extest("http://[fec0::X]:99"),
+ extest("http:\\www.foo.com"),
+ extest("http://w_09ww.foo.com"),
+ extest("http://w&09ww.foo.com/p"),
+ extest("http://www+foo.com"),
extest("http:")
};
From ee1006e3bd0f49054996f387b8ec20361716fa2d Mon Sep 17 00:00:00 2001
From: Robert Field
Date: Mon, 4 Nov 2013 10:12:18 -0800
Subject: [PATCH 015/110] 7194897: JSR 292: Cannot create more than 16
instances of an anonymous class 8027681: Lambda serialization fails once
reflection proxy generation kicks in
Co-authored-by: Joel Borggren-Franck
Co-authored-by: Brian Goetz
Reviewed-by: ksrini, briangoetz, jfranck
---
.../NativeConstructorAccessorImpl.java | 9 ++-
.../sun/reflect/NativeMethodAccessorImpl.java | 9 ++-
.../classes/sun/reflect/misc/ReflectUtil.java | 11 +++-
.../lambda/RepetitiveLambdaSerialization.java | 53 ++++++++++++++++
.../lang/invoke/SerializedLambdaTest.java | 12 ++--
.../ManyNewInstanceAnonTest.java | 62 +++++++++++++++++++
6 files changed, 147 insertions(+), 9 deletions(-)
create mode 100644 jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java
create mode 100644 jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java
diff --git a/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java b/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java
index 4f91ddc4460..d56c3caab08 100644
--- a/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java
+++ b/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,6 +26,7 @@
package sun.reflect;
import java.lang.reflect.*;
+import sun.reflect.misc.ReflectUtil;
/** Used only for the first few invocations of a Constructor;
afterward, switches to bytecode-based implementation */
@@ -44,7 +45,11 @@ class NativeConstructorAccessorImpl extends ConstructorAccessorImpl {
IllegalArgumentException,
InvocationTargetException
{
- if (++numInvocations > ReflectionFactory.inflationThreshold()) {
+ // We can't inflate a constructor belonging to a vm-anonymous class
+ // because that kind of class can't be referred to by name, hence can't
+ // be found from the generated bytecode.
+ if (++numInvocations > ReflectionFactory.inflationThreshold()
+ && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
new MethodAccessorGenerator().
generateConstructor(c.getDeclaringClass(),
diff --git a/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java b/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java
index 93f186b7b49..b1d39e7c965 100644
--- a/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java
+++ b/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,6 +26,7 @@
package sun.reflect;
import java.lang.reflect.*;
+import sun.reflect.misc.ReflectUtil;
/** Used only for the first few invocations of a Method; afterward,
switches to bytecode-based implementation */
@@ -42,7 +43,11 @@ class NativeMethodAccessorImpl extends MethodAccessorImpl {
public Object invoke(Object obj, Object[] args)
throws IllegalArgumentException, InvocationTargetException
{
- if (++numInvocations > ReflectionFactory.inflationThreshold()) {
+ // We can't inflate methods belonging to vm-anonymous classes because
+ // that kind of class can't be referred to by name, hence can't be
+ // found from the generated bytecode.
+ if (++numInvocations > ReflectionFactory.inflationThreshold()
+ && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
MethodAccessorImpl acc = (MethodAccessorImpl)
new MethodAccessorGenerator().
generateMethod(method.getDeclaringClass(),
diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java
index 1f871e8de02..4316d422c39 100644
--- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java
+++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -298,4 +298,13 @@ public final class ReflectUtil {
}
return false;
}
+
+ /**
+ * Checks if {@code Class cls} is a VM-anonymous class
+ * as defined by {@link sun.misc.Unsafe#defineAnonymousClass}
+ * (not to be confused with a Java Language anonymous inner class).
+ */
+ public static boolean isVMAnonymousClass(Class> cls) {
+ return cls.getSimpleName().contains("/");
+ }
}
diff --git a/jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java b/jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java
new file mode 100644
index 00000000000..5c57615a307
--- /dev/null
+++ b/jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 8027681
+ * @summary Lambda serialization fails once reflection proxy generation kicks in
+ * @author Robert Field
+ * @run main/othervm RepetitiveLambdaSerialization
+ */
+
+import java.io.*;
+
+public class RepetitiveLambdaSerialization {
+
+ static final int REPS = 20;
+
+ public static void main(String[] args) throws Exception {
+ LSI ls = z -> "[" + z + "]";
+ for (int i = 0; i < REPS; ++i) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutput out = new ObjectOutputStream(baos);
+ out.writeObject(ls);
+ out.flush();
+ out.close();
+ }
+ System.out.println("Passed.");
+ }
+}
+
+interface LSI extends Serializable {
+ String convert(String x);
+}
diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java
index 8f01dada86f..fdbd689ad36 100644
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -56,14 +56,18 @@ import static org.testng.Assert.fail;
*/
@Test
public class SerializedLambdaTest {
+ public static final int REPS = 50;
+
@SuppressWarnings("unchecked")
private void assertSerial(T p, Consumer asserter) throws IOException, ClassNotFoundException {
asserter.accept(p);
- byte[] bytes = serialize(p);
- assertTrue(bytes.length > 0);
+ for (int i=0; i 0);
- asserter.accept((T) deserialize(bytes));
+ asserter.accept((T) deserialize(bytes));
+ }
}
private void assertNotSerial(Predicate p, Consumer> asserter)
diff --git a/jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java b/jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java
new file mode 100644
index 00000000000..b931b8a65f8
--- /dev/null
+++ b/jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 7194897
+ * @summary JSR 292: Cannot create more than 16 instances of an anonymous class
+ * @author Robert Field
+ * @library /lib/testlibrary
+ * @compile -XDignore.symbol.file ManyNewInstanceAnonTest.java
+ * @run main ClassFileInstaller ManyNewInstanceAnonTest
+ * @run main/othervm -Xbootclasspath/a:. -Xverify:all ManyNewInstanceAnonTest
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import sun.misc.Unsafe;
+
+public class ManyNewInstanceAnonTest {
+
+ static final int REPS = 20;
+ static final Class> klass = ManyNewInstanceAnonTest.class;
+
+ public static void main(String[] args) throws Exception {
+ Class> c = Unsafe.getUnsafe().defineAnonymousClass(klass, readClassFile(), null);
+ for (int i = 0; i < REPS; ++i) {
+ System.out.printf("%d: %s\n", i, c.newInstance());
+ }
+ System.out.println("Passed.");
+ }
+
+ private static byte[] readClassFile() throws Exception {
+ try (InputStream in = klass.getResourceAsStream(klass.getSimpleName() + ".class");
+ ByteArrayOutputStream out = new ByteArrayOutputStream())
+ {
+ int b;
+ while ((b = in.read()) != -1) {
+ out.write(b);
+ }
+ return out.toByteArray();
+ }
+ }
+}
From 79b1f94594b1743ed2f45251b63123c4ae60f1ba Mon Sep 17 00:00:00 2001
From: Andreas Lundblad
Date: Mon, 4 Nov 2013 15:21:47 +0100
Subject: [PATCH 016/110] 8016725: TEST_BUG:
java/lang/reflect/Method/DefaultMethodModeling.java failing intermittently
Moved DefaultMethodModeling.java to its own directory to avoid conflicts with Equals.java.
Reviewed-by: darcy
---
.../Method/{ => defaultMethodModeling}/DefaultMethodModeling.java | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename jdk/test/java/lang/reflect/Method/{ => defaultMethodModeling}/DefaultMethodModeling.java (100%)
diff --git a/jdk/test/java/lang/reflect/Method/DefaultMethodModeling.java b/jdk/test/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java
similarity index 100%
rename from jdk/test/java/lang/reflect/Method/DefaultMethodModeling.java
rename to jdk/test/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java
From 3fdca184336549a0dcc7a20a96348bcbd61a72aa Mon Sep 17 00:00:00 2001
From: Dan Xu
Date: Mon, 4 Nov 2013 15:48:08 -0800
Subject: [PATCH 017/110] 8027612: java/io/File/MaxPathLength.java fails
intermittently in the clean-up stage
Reviewed-by: chegar
---
jdk/test/java/io/File/MaxPathLength.java | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/jdk/test/java/io/File/MaxPathLength.java b/jdk/test/java/io/File/MaxPathLength.java
index 9fd6183f36d..cdda0471446 100644
--- a/jdk/test/java/io/File/MaxPathLength.java
+++ b/jdk/test/java/io/File/MaxPathLength.java
@@ -28,6 +28,8 @@
import java.io.*;
import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.DirectoryNotEmptyException;
public class MaxPathLength {
private static String sep = File.separator;
@@ -182,7 +184,18 @@ public class MaxPathLength {
} finally {
// Clean up
for (int i = 0; i < max; i++) {
- Files.deleteIfExists((new File(created[i])).toPath());
+ Path p = (new File(created[i])).toPath();
+ try {
+ Files.deleteIfExists(p);
+ // Test if the file is really deleted and wait for 1 second at most
+ for (int j = 0; j < 10 && Files.exists(p); j++) {
+ Thread.sleep(100);
+ }
+ } catch (DirectoryNotEmptyException ex) {
+ // Give up the clean-up, let jtreg handle it.
+ System.err.println("Dir, " + p + ", is not empty");
+ break;
+ }
}
}
}
From fe6f3e2439db3d75d114c98cf661e8ecb32824fc Mon Sep 17 00:00:00 2001
From: Paul Sandoz
Date: Tue, 5 Nov 2013 12:08:12 +0100
Subject: [PATCH 018/110] 8027712: DistinctOpTest fails for unordered test
Reviewed-by: henryjen, alanb
---
.../openjdk/tests/java/util/stream/DistinctOpTest.java | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java
index 7d26925a1f2..69432cfedf6 100644
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java
@@ -54,10 +54,14 @@ public class DistinctOpTest extends OpTestCase {
// These tests should short-circuit, otherwise will fail with a time-out
// or an OOME
- Integer one = Stream.iterate(1, i -> i + 1).unordered().parallel().distinct().findAny().get();
- assertEquals(one.intValue(), 1);
+ // Note that since the streams are unordered and any element is requested
+ // (a non-deterministic process) the only assertion that can be made is
+ // that an element should be found
- Optional oi = ThreadLocalRandom.current().ints().boxed().parallel().distinct().findAny();
+ Optional oi = Stream.iterate(1, i -> i + 1).unordered().parallel().distinct().findAny();
+ assertTrue(oi.isPresent());
+
+ oi = ThreadLocalRandom.current().ints().boxed().parallel().distinct().findAny();
assertTrue(oi.isPresent());
}
From 33be168ccb7c6d033fce9cbe541f4c118811aa46 Mon Sep 17 00:00:00 2001
From: Joe Wang
Date: Tue, 5 Nov 2013 11:18:20 -0800
Subject: [PATCH 019/110] 8027860: [TEST_BUG] File not closed in
javax/xml/jaxp/parsers/8022548/XOMParserTest.java
Reviewed-by: alanb
---
.../jaxp/parsers/8022548/XOMParserTest.java | 26 +++++++++----------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java b/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java
index ba12d0ddc86..15915d04912 100644
--- a/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java
+++ b/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java
@@ -22,7 +22,8 @@
*/
/**
- * @test @bug 8022548
+ * @test
+ * @bug 8022548
* @summary test that a parser can use DTDConfiguration
* @run main XOMParserTest
*/
@@ -60,30 +61,27 @@ public class XOMParserTest extends TestBase {
}
public final void testTransform() {
+ String inFilename = filePath + "/JDK8022548.xml";
+ String xslFilename = filePath + "/JDK8022548.xsl";
+ String outFilename = "JDK8022548.out";
- try {
+ try (InputStream xslInput = new FileInputStream(xslFilename);
+ InputStream xmlInput = new FileInputStream(inFilename);
+ OutputStream out = new FileOutputStream(outFilename);
+ ) {
- String inFilename = filePath + "/JDK8022548.xml";
- String xslFilename = filePath + "/JDK8022548.xsl";
- String outFilename = "JDK8022548.out";
StringWriter sw = new StringWriter();
// Create transformer factory
TransformerFactory factory = TransformerFactory.newInstance();
- // set the translet name
-// factory.setAttribute("translet-name", "myTranslet");
-
- // set the destination directory
-// factory.setAttribute("destination-directory", "c:\\temp");
-// factory.setAttribute("generate-translet", Boolean.TRUE);
// Use the factory to create a template containing the xsl file
- Templates template = factory.newTemplates(new StreamSource(new FileInputStream(xslFilename)));
+ Templates template = factory.newTemplates(new StreamSource(xslInput));
// Use the template to create a transformer
Transformer xformer = template.newTransformer();
// Prepare the input and output files
- Source source = new StreamSource(new FileInputStream(inFilename));
- Result result = new StreamResult(new FileOutputStream(outFilename));
+ Source source = new StreamSource(xmlInput);
+ Result result = new StreamResult(outFilename);
//Result result = new StreamResult(sw);
// Apply the xsl file to the source file and write the result to the output file
xformer.transform(source, result);
From 1b7f902c51a23227550663bbebbe4e9a0591d56b Mon Sep 17 00:00:00 2001
From: Mandy Chung
Date: Tue, 5 Nov 2013 17:33:26 -0800
Subject: [PATCH 020/110] 8022208: Intermittent test failures in
java/lang/Thread/ThreadStateTest.java 6944188:
ThreadMXBean/ThreadStateTest.java fails intermittently
Reviewed-by: dholmes, chegar
---
.../lang/Thread/ThreadStateController.java | 340 ++++++++++++++
.../java/lang/Thread/ThreadStateTest.java | 304 ++-----------
.../ThreadMXBean/ThreadMXBeanStateTest.java | 230 ++++++++++
.../ThreadMXBean/ThreadStateTest.java | 424 ------------------
4 files changed, 597 insertions(+), 701 deletions(-)
create mode 100644 jdk/test/java/lang/Thread/ThreadStateController.java
create mode 100644 jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java
delete mode 100644 jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java
diff --git a/jdk/test/java/lang/Thread/ThreadStateController.java b/jdk/test/java/lang/Thread/ThreadStateController.java
new file mode 100644
index 00000000000..2d876b0ec41
--- /dev/null
+++ b/jdk/test/java/lang/Thread/ThreadStateController.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * ThreadStateController allows a thread to request this thread to transition
+ * to a specific thread state. The {@linkplain #transitionTo request} is
+ * a blocking call that the calling thread will wait until this thread is about
+ * going to the new state. Only one request of state transition at a time
+ * is supported (the Phaser expects only parties of 2 to arrive and advance
+ * to next phase).
+ */
+public class ThreadStateController extends Thread {
+ // used to achieve waiting states
+ private final Object lock;
+ public ThreadStateController(String name, Object lock) {
+ super(name);
+ this.lock = lock;
+ }
+
+ public void checkThreadState(Thread.State expected) {
+ // maximum number of retries when checking for thread state.
+ final int MAX_RETRY = 500;
+
+ // wait for the thread to transition to the expected state.
+ // There is a small window between the thread checking the state
+ // and the thread actual entering that state.
+ Thread.State state;
+ int retryCount=0;
+ while ((state = getState()) != expected && retryCount < MAX_RETRY) {
+ pause(10);
+ retryCount++;
+ }
+
+ if (state == null) {
+ throw new RuntimeException(getName() + " expected to have " +
+ expected + " but got null.");
+ }
+
+ if (state != expected) {
+ throw new RuntimeException(String.format("%s expected in %s state but got %s " +
+ "(iterations %d interrupted %d)%n",
+ getName(), expected, state, iterations.get(), interrupted.get()));
+ }
+ }
+
+ public static void pause(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Phaser to sync between the main thread putting
+ // this thread into various states
+ private final Phaser phaser = new Phaser(2);
+ private volatile int newState = S_RUNNABLE;
+ private volatile int state = 0;
+ private boolean done = false;
+
+ private static final int S_RUNNABLE = 1;
+ private static final int S_BLOCKED = 2;
+ private static final int S_WAITING = 3;
+ private static final int S_TIMED_WAITING = 4;
+ private static final int S_PARKED = 5;
+ private static final int S_TIMED_PARKED = 6;
+ private static final int S_SLEEPING = 7;
+ private static final int S_TERMINATE = 8;
+
+ // for debugging
+ private AtomicInteger iterations = new AtomicInteger();
+ private AtomicInteger interrupted = new AtomicInteger();
+ public void run() {
+ // this thread has started
+ while (!done) {
+ // state transition
+ int nextState = state;
+ if (newState != state) {
+ nextState = newState;
+ iterations.set(0);
+ interrupted.set(0);
+ }
+ iterations.incrementAndGet();
+ switch (nextState) {
+ case S_RUNNABLE: {
+ stateChange(nextState);
+ double sum = 0;
+ for (int i = 0; i < 1000; i++) {
+ double r = Math.random();
+ double x = Math.pow(3, r);
+ sum += x - r;
+ }
+ break;
+ }
+ case S_BLOCKED: {
+ System.out.format("%d: %s is going to block (interations %d)%n",
+ getId(), getName(), iterations.get());
+ stateChange(nextState);
+ // going to block on lock
+ synchronized (lock) {
+ System.out.format("%d: %s acquired the lock (interations %d)%n",
+ getId(), getName(), iterations.get());
+ try {
+ // this thread has escaped the BLOCKED state
+ // release the lock and a short wait before continue
+ lock.wait(10);
+ } catch (InterruptedException e) {
+ // ignore
+ interrupted.incrementAndGet();
+ }
+ }
+ break;
+ }
+ case S_WAITING: {
+ synchronized (lock) {
+ System.out.format("%d: %s is going to waiting (interations %d interrupted %d)%n",
+ getId(), getName(), iterations.get(), interrupted.get());
+ try {
+ stateChange(nextState);
+ lock.wait();
+ System.out.format("%d: %s wakes up from waiting (interations %d interrupted %d)%n",
+ getId(), getName(), iterations.get(), interrupted.get());
+ } catch (InterruptedException e) {
+ // ignore
+ interrupted.incrementAndGet();
+ }
+ }
+ break;
+ }
+ case S_TIMED_WAITING: {
+ synchronized (lock) {
+ System.out.format("%d: %s is going to timed waiting (interations %d interrupted %d)%n",
+ getId(), getName(), iterations.get(), interrupted.get());
+ try {
+ stateChange(nextState);
+ lock.wait(10000);
+ System.out.format("%d: %s wakes up from timed waiting (interations %d interrupted %d)%n",
+ getId(), getName(), iterations.get(), interrupted.get());
+ } catch (InterruptedException e) {
+ // ignore
+ interrupted.incrementAndGet();
+ }
+ }
+ break;
+ }
+ case S_PARKED: {
+ System.out.format("%d: %s is going to park (interations %d)%n",
+ getId(), getName(), iterations.get());
+ stateChange(nextState);
+ LockSupport.park();
+ break;
+ }
+ case S_TIMED_PARKED: {
+ System.out.format("%d: %s is going to timed park (interations %d)%n",
+ getId(), getName(), iterations.get());
+ long deadline = System.currentTimeMillis() + 10000*1000;
+ stateChange(nextState);
+ LockSupport.parkUntil(deadline);
+ break;
+ }
+ case S_SLEEPING: {
+ System.out.format("%d: %s is going to sleep (interations %d interrupted %d)%n",
+ getId(), getName(), iterations.get(), interrupted.get());
+ try {
+ stateChange(nextState);
+ Thread.sleep(1000000);
+ } catch (InterruptedException e) {
+ // finish sleeping
+ interrupted.incrementAndGet();
+ }
+ break;
+ }
+ case S_TERMINATE: {
+ done = true;
+ stateChange(nextState);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Change the state if it matches newState.
+ */
+ private void stateChange(int nextState) {
+ // no state change
+ if (state == nextState)
+ return;
+
+ // transition to the new state
+ if (newState == nextState) {
+ state = nextState;
+ phaser.arrive();
+ System.out.format("%d: state change: %s %s%n",
+ getId(), toStateName(nextState), phaserToString(phaser));
+ return;
+ }
+
+ // should never reach here
+ throw new RuntimeException("current " + state + " next " + nextState +
+ " new state " + newState);
+ }
+
+ /**
+ * Blocks until this thread transitions to the given state
+ */
+ public void transitionTo(Thread.State tstate) throws InterruptedException {
+ switch (tstate) {
+ case RUNNABLE:
+ nextState(S_RUNNABLE);
+ break;
+ case BLOCKED:
+ nextState(S_BLOCKED);
+ break;
+ case WAITING:
+ nextState(S_WAITING);
+ break;
+ case TIMED_WAITING:
+ nextState(S_TIMED_WAITING);
+ break;
+ case TERMINATED:
+ nextState(S_TERMINATE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Blocks until this thread transitions to sleeping
+ */
+ public void transitionToSleep() throws InterruptedException {
+ nextState(S_SLEEPING);
+ }
+
+ /**
+ * Blocks until this thread transitions to park or timed park
+ */
+ public void transitionToPark(boolean timed) throws InterruptedException {
+ nextState(timed ? S_TIMED_PARKED : S_PARKED);
+ }
+
+ private void nextState(int s) throws InterruptedException {
+ final long id = Thread.currentThread().getId();
+ System.out.format("%d: wait until the thread transitions to %s %s%n",
+ id, toStateName(s), phaserToString(phaser));
+ this.newState = s;
+ int phase = phaser.arrive();
+ System.out.format("%d: awaiting party arrive %s %s%n",
+ id, toStateName(s), phaserToString(phaser));
+ for (;;) {
+ // when this thread has changed its state before it waits or parks
+ // on a lock, a potential race might happen if it misses the notify
+ // or unpark. Hence await for the phaser to advance with timeout
+ // to cope with this race condition.
+ switch (state) {
+ case S_WAITING:
+ case S_TIMED_WAITING:
+ synchronized (lock) {
+ lock.notify();
+ }
+ break;
+ case S_PARKED:
+ case S_TIMED_PARKED:
+ LockSupport.unpark(this);
+ break;
+ case S_SLEEPING:
+ this.interrupt();
+ break;
+ case S_BLOCKED:
+ default:
+ break;
+ }
+ try {
+ phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS);
+ System.out.format("%d: arrived at %s %s%n",
+ id, toStateName(s), phaserToString(phaser));
+ return;
+ } catch (TimeoutException ex) {
+ // this thread hasn't arrived at this phase
+ System.out.format("%d: Timeout: %s%n", id, phaser);
+ }
+ }
+ }
+ private String phaserToString(Phaser p) {
+ return "[phase = " + p.getPhase() +
+ " parties = " + p.getRegisteredParties() +
+ " arrived = " + p.getArrivedParties() + "]";
+ }
+ private String toStateName(int state) {
+ switch (state) {
+ case S_RUNNABLE:
+ return "runnable";
+ case S_WAITING:
+ return "waiting";
+ case S_TIMED_WAITING:
+ return "timed waiting";
+ case S_PARKED:
+ return "parked";
+ case S_TIMED_PARKED:
+ return "timed parked";
+ case S_SLEEPING:
+ return "sleeping";
+ case S_BLOCKED:
+ return "blocked";
+ case S_TERMINATE:
+ return "terminated";
+ default:
+ return "unknown " + state;
+ }
+ }
+}
diff --git a/jdk/test/java/lang/Thread/ThreadStateTest.java b/jdk/test/java/lang/Thread/ThreadStateTest.java
index c4fa18850b2..b73421eb4c0 100644
--- a/jdk/test/java/lang/Thread/ThreadStateTest.java
+++ b/jdk/test/java/lang/Thread/ThreadStateTest.java
@@ -21,77 +21,64 @@
* questions.
*/
+import static java.lang.Thread.State.*;
+
/*
* @test
- * @bug 5014783
+ * @bug 5014783 8022208
* @summary Basic unit test of thread states returned by
* Thread.getState().
*
* @author Mandy Chung
- *
- * @build ThreadStateTest
+ * @build ThreadStateTest ThreadStateController
* @run main ThreadStateTest
*/
-import java.util.concurrent.locks.LockSupport;
-import java.util.concurrent.Phaser;
-
public class ThreadStateTest {
- // maximum number of retries when checking for thread state.
- static final int MAX_RETRY = 500;
-
private static boolean testFailed = false;
// used to achieve waiting states
- static final Object globalLock = new Object();
+ private static final Object globalLock = new Object();
- public static void main(String[] argv) {
+ public static void main(String[] argv) throws Exception {
// Call Thread.getState to force all initialization done
// before test verification begins.
Thread.currentThread().getState();
- MyThread myThread = new MyThread("MyThread");
+ ThreadStateController thread = new ThreadStateController("StateChanger", globalLock);
+ thread.setDaemon(true);
// before myThread starts
- checkThreadState(myThread, Thread.State.NEW);
+ thread.checkThreadState(NEW);
- myThread.start();
- myThread.waitUntilStarted();
- checkThreadState(myThread, Thread.State.RUNNABLE);
+ thread.start();
+ thread.transitionTo(RUNNABLE);
+ thread.checkThreadState(RUNNABLE);
synchronized (globalLock) {
- myThread.goBlocked();
- checkThreadState(myThread, Thread.State.BLOCKED);
+ thread.transitionTo(BLOCKED);
+ thread.checkThreadState(BLOCKED);
}
- myThread.goWaiting();
- checkThreadState(myThread, Thread.State.WAITING);
+ thread.transitionTo(WAITING);
+ thread.checkThreadState(WAITING);
- myThread.goTimedWaiting();
- checkThreadState(myThread, Thread.State.TIMED_WAITING);
+ thread.transitionTo(TIMED_WAITING);
+ thread.checkThreadState(TIMED_WAITING);
+ thread.transitionToPark(true /* timed park*/);
+ thread.checkThreadState(TIMED_WAITING);
- /*
- *********** park and parkUntil seems not working
- * ignore this case for now.
- * Bug ID 5062095
- ***********************************************
+ thread.transitionToPark(false /* indefinite park */);
+ thread.checkThreadState(WAITING);
- myThread.goParked();
- checkThreadState(myThread, Thread.State.WAITING);
+ thread.transitionToSleep();
+ thread.checkThreadState(TIMED_WAITING);
- myThread.goTimedParked();
- checkThreadState(myThread, Thread.State.TIMED_WAITING);
- */
-
-
- myThread.goSleeping();
- checkThreadState(myThread, Thread.State.TIMED_WAITING);
-
- myThread.terminate();
- checkThreadState(myThread, Thread.State.TERMINATED);
+ thread.transitionTo(TERMINATED);
+ thread.checkThreadState(TERMINATED);
try {
- myThread.join();
+ thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("Unexpected exception.");
@@ -102,241 +89,4 @@ public class ThreadStateTest {
throw new RuntimeException("TEST FAILED.");
System.out.println("Test passed.");
}
-
- private static void checkThreadState(Thread t, Thread.State expected) {
- // wait for the thread to transition to the expected state.
- // There is a small window between the thread checking the state
- // and the thread actual entering that state.
- Thread.State state;
- int retryCount=0;
- while ((state = t.getState()) != expected && retryCount < MAX_RETRY) {
- if (state != Thread.State.RUNNABLE) {
- throw new RuntimeException("Thread not in expected state yet," +
- " but it should at least be RUNNABLE");
- }
- goSleep(10);
- retryCount++;
- }
-
- System.out.println("Checking thread state " + state);
- if (state == null) {
- throw new RuntimeException(t.getName() + " expected to have " +
- expected + " but got null.");
- }
-
- if (state != expected) {
- throw new RuntimeException(t.getName() + " expected to have " +
- expected + " but got " + state);
- }
- }
-
- private static void goSleep(long ms) {
- try {
- Thread.sleep(ms);
- } catch (InterruptedException e) {
- e.printStackTrace();
- System.out.println("Unexpected exception.");
- testFailed = true;
- }
- }
-
- static class MyThread extends Thread {
- // Phaser to sync between the main thread putting
- // this thread into various states
- private Phaser phaser = new Phaser(2);
-
- MyThread(String name) {
- super(name);
- }
-
- private final int RUNNABLE = 0;
- private final int BLOCKED = 1;
- private final int WAITING = 2;
- private final int TIMED_WAITING = 3;
- private final int PARKED = 4;
- private final int TIMED_PARKED = 5;
- private final int SLEEPING = 6;
- private final int TERMINATE = 7;
-
- private volatile int state = RUNNABLE;
-
- private boolean done = false;
- public void run() {
- // Signal main thread to continue.
- phaser.arriveAndAwaitAdvance();
-
- while (!done) {
- switch (state) {
- case RUNNABLE: {
- double sum = 0;
- for (int i = 0; i < 1000; i++) {
- double r = Math.random();
- double x = Math.pow(3, r);
- sum += x - r;
- }
- break;
- }
- case BLOCKED: {
- // signal main thread.
- phaser.arrive();
- System.out.println(" myThread is going to block.");
- synchronized (globalLock) {
- // finish blocking
- state = RUNNABLE;
- }
- break;
- }
- case WAITING: {
- synchronized (globalLock) {
- // signal main thread.
- phaser.arrive();
- System.out.println(" myThread is going to wait.");
- try {
- globalLock.wait();
- } catch (InterruptedException e) {
- // ignore
- }
- }
- break;
- }
- case TIMED_WAITING: {
- synchronized (globalLock) {
- // signal main thread.
- phaser.arrive();
- System.out.println(" myThread is going to timed wait.");
- try {
- globalLock.wait(10000);
- } catch (InterruptedException e) {
- // ignore
- }
- }
- break;
- }
- case PARKED: {
- // signal main thread.
- phaser.arrive();
- System.out.println(" myThread is going to park.");
- LockSupport.park();
- // give a chance for the main thread to block
- goSleep(10);
- break;
- }
- case TIMED_PARKED: {
- // signal main thread.
- phaser.arrive();
- System.out.println(" myThread is going to timed park.");
- long deadline = System.currentTimeMillis() + 10000*1000;
- LockSupport.parkUntil(deadline);
-
- // give a chance for the main thread to block
- goSleep(10);
- break;
- }
- case SLEEPING: {
- // signal main thread.
- phaser.arrive();
- System.out.println(" myThread is going to sleep.");
- try {
- Thread.sleep(1000000);
- } catch (InterruptedException e) {
- // finish sleeping
- }
- break;
- }
- case TERMINATE: {
- done = true;
- // signal main thread.
- phaser.arrive();
- break;
- }
- default:
- break;
- }
- }
- }
-
- public void waitUntilStarted() {
- // wait for MyThread.
- phaser.arriveAndAwaitAdvance();
- }
-
- public void goBlocked() {
- System.out.println("Waiting myThread to go blocked.");
- setState(BLOCKED);
- // wait for MyThread to get to a point just before being blocked
- phaser.arriveAndAwaitAdvance();
- }
-
- public void goWaiting() {
- System.out.println("Waiting myThread to go waiting.");
- setState(WAITING);
- // wait for MyThread to get to just before wait on object.
- phaser.arriveAndAwaitAdvance();
- }
-
- public void goTimedWaiting() {
- System.out.println("Waiting myThread to go timed waiting.");
- setState(TIMED_WAITING);
- // wait for MyThread to get to just before timed wait call.
- phaser.arriveAndAwaitAdvance();
- }
-
- public void goParked() {
- System.out.println("Waiting myThread to go parked.");
- setState(PARKED);
- // wait for MyThread to get to just before parked.
- phaser.arriveAndAwaitAdvance();
- }
-
- public void goTimedParked() {
- System.out.println("Waiting myThread to go timed parked.");
- setState(TIMED_PARKED);
- // wait for MyThread to get to just before timed park.
- phaser.arriveAndAwaitAdvance();
- }
-
- public void goSleeping() {
- System.out.println("Waiting myThread to go sleeping.");
- setState(SLEEPING);
- // wait for MyThread to get to just before sleeping
- phaser.arriveAndAwaitAdvance();
- }
-
- public void terminate() {
- System.out.println("Waiting myThread to terminate.");
- setState(TERMINATE);
- // wait for MyThread to get to just before terminate
- phaser.arriveAndAwaitAdvance();
- }
-
- private void setState(int newState) {
- switch (state) {
- case BLOCKED:
- while (state == BLOCKED) {
- goSleep(10);
- }
- state = newState;
- break;
- case WAITING:
- case TIMED_WAITING:
- state = newState;
- synchronized (globalLock) {
- globalLock.notify();
- }
- break;
- case PARKED:
- case TIMED_PARKED:
- state = newState;
- LockSupport.unpark(this);
- break;
- case SLEEPING:
- state = newState;
- this.interrupt();
- break;
- default:
- state = newState;
- break;
- }
- }
- }
}
diff --git a/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java
new file mode 100644
index 00000000000..dc4fe3d1016
--- /dev/null
+++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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 4967283 5080203 8022208
+ * @summary Basic unit test of thread states returned by
+ * ThreadMXBean.getThreadInfo.getThreadState().
+ * It also tests lock information returned by ThreadInfo.
+ *
+ * @author Mandy Chung
+ *
+ * @library ../../Thread
+ * @build ThreadMXBeanStateTest ThreadStateController
+ * @run main ThreadMXBeanStateTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+import java.lang.management.ThreadInfo;
+import static java.lang.Thread.State.*;
+
+public class ThreadMXBeanStateTest {
+ private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
+
+ static class Lock {
+ private String name;
+ Lock(String name) {
+ this.name = name;
+ }
+ public String toString() {
+ return name;
+ }
+ }
+ private static Lock globalLock = new Lock("my lock");
+
+ public static void main(String[] argv) throws Exception {
+ // Force thread state initialization now before the test
+ // verification begins.
+ Thread.currentThread().getState();
+ ThreadStateController thread = new ThreadStateController("StateChanger", globalLock);
+ thread.setDaemon(true);
+
+ // before myThread starts
+ thread.checkThreadState(NEW);
+
+ thread.start();
+ thread.transitionTo(RUNNABLE);
+ thread.checkThreadState(RUNNABLE);
+ checkLockInfo(thread, RUNNABLE, null, null);
+
+ thread.suspend();
+ ThreadStateController.pause(10);
+ thread.checkThreadState(RUNNABLE);
+ checkSuspendedThreadState(thread, RUNNABLE);
+ thread.resume();
+
+ synchronized (globalLock) {
+ thread.transitionTo(BLOCKED);
+ thread.checkThreadState(BLOCKED);
+ checkLockInfo(thread, BLOCKED,
+ globalLock, Thread.currentThread());
+ }
+
+ thread.transitionTo(WAITING);
+ thread.checkThreadState(WAITING);
+ checkLockInfo(thread, Thread.State.WAITING,
+ globalLock, null);
+
+ thread.transitionTo(TIMED_WAITING);
+ thread.checkThreadState(TIMED_WAITING);
+ checkLockInfo(thread, TIMED_WAITING,
+ globalLock, null);
+
+
+ thread.transitionToPark(true /* timed park */);
+ thread.checkThreadState(TIMED_WAITING);
+ checkLockInfo(thread, TIMED_WAITING, null, null);
+
+ thread.transitionToPark(false /* indefinite park */);
+ thread.checkThreadState(WAITING);
+ checkLockInfo(thread, WAITING, null, null);
+
+ thread.transitionToSleep();
+ thread.checkThreadState(TIMED_WAITING);
+ checkLockInfo(thread, TIMED_WAITING, null, null);
+
+ thread.transitionTo(TERMINATED);
+ thread.checkThreadState(TERMINATED);
+
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ System.out.println("TEST FAILED: Unexpected exception.");
+ throw new RuntimeException(e);
+ }
+ System.out.println("Test passed.");
+ }
+
+ private static void checkSuspendedThreadState(ThreadStateController t, Thread.State state) {
+ ThreadInfo info = getThreadInfo(t, state);
+ if (info == null) {
+ throw new RuntimeException(t.getName() +
+ " expected to have ThreadInfo " +
+ " but got null.");
+ }
+
+ if (info.getThreadState() != state) {
+ throw new RuntimeException(t.getName() + " expected to be in " +
+ state + " state but got " + info.getThreadState());
+ }
+
+ if (!info.isSuspended()) {
+ throw new RuntimeException(t.getName() + " expected to be suspended " +
+ " but isSuspended() returns " + info.isSuspended());
+ }
+ }
+
+ private static String getLockName(Object lock) {
+ if (lock == null) return null;
+
+ return lock.getClass().getName() + '@' +
+ Integer.toHexString(System.identityHashCode(lock));
+ }
+
+ // maximum number of retries when checking for thread state.
+ private static final int MAX_RETRY = 500;
+ private static ThreadInfo getThreadInfo(ThreadStateController t, Thread.State expected) {
+ // wait for the thread to transition to the expected state.
+ // There is a small window between the thread checking the state
+ // and the thread actual entering that state.
+ int retryCount=0;
+ ThreadInfo info = tm.getThreadInfo(t.getId());
+ while (info.getThreadState() != expected && retryCount < MAX_RETRY) {
+ ThreadStateController.pause(10);
+ retryCount++;
+ info = tm.getThreadInfo(t.getId());
+ }
+ return info;
+ }
+
+ private static void checkLockInfo(ThreadStateController t, Thread.State state,
+ Object lock, Thread owner) {
+ ThreadInfo info = getThreadInfo(t, state);
+ if (info == null) {
+ throw new RuntimeException(t.getName() +
+ " expected to have ThreadInfo " +
+ " but got null.");
+ }
+
+ if (info.getThreadState() != state) {
+ throw new RuntimeException(t.getName() + " expected to be in " +
+ state + " state but got " + info.getThreadState());
+ }
+
+ if (lock == null && info.getLockName() != null) {
+ throw new RuntimeException(t.getName() +
+ " expected not to be blocked on any lock" +
+ " but got " + info.getLockName());
+ }
+ String expectedLockName = getLockName(lock);
+ if (lock != null && info.getLockName() == null) {
+ throw new RuntimeException(t.getName() +
+ " expected to be blocked on lock [" + expectedLockName +
+ "] but got null.");
+ }
+
+ if (lock != null && !expectedLockName.equals(info.getLockName())) {
+ throw new RuntimeException(t.getName() +
+ " expected to be blocked on lock [" + expectedLockName +
+ "] but got [" + info.getLockName() + "].");
+ }
+
+ if (owner == null && info.getLockOwnerName() != null) {
+ throw new RuntimeException("Lock owner is expected " +
+ " to be null but got " + info.getLockOwnerName());
+ }
+
+ if (owner != null && info.getLockOwnerName() == null) {
+ throw new RuntimeException("Lock owner is expected to be " +
+ owner.getName() +
+ " but got null.");
+ }
+ if (owner != null && !info.getLockOwnerName().equals(owner.getName())) {
+ throw new RuntimeException("Lock owner is expected to be " +
+ owner.getName() +
+ " but got " + owner.getName());
+ }
+ if (owner == null && info.getLockOwnerId() != -1) {
+ throw new RuntimeException("Lock owner is expected " +
+ " to be -1 but got " + info.getLockOwnerId());
+ }
+
+ if (owner != null && info.getLockOwnerId() <= 0) {
+ throw new RuntimeException("Lock owner is expected to be " +
+ owner.getName() + "(id = " + owner.getId() +
+ ") but got " + info.getLockOwnerId());
+ }
+ if (owner != null && info.getLockOwnerId() != owner.getId()) {
+ throw new RuntimeException("Lock owner is expected to be " +
+ owner.getName() + "(id = " + owner.getId() +
+ ") but got " + info.getLockOwnerId());
+ }
+ if (info.isSuspended()) {
+ throw new RuntimeException(t.getName() +
+ " isSuspended() returns " + info.isSuspended());
+ }
+ }
+}
diff --git a/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java b/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java
deleted file mode 100644
index 1b767e46225..00000000000
--- a/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * 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 4967283 5080203
- * @summary Basic unit test of thread states returned by
- * ThreadMXBean.getThreadInfo.getThreadState().
- * It also tests lock information returned by ThreadInfo.
- *
- * @author Mandy Chung
- *
- * @build ThreadExecutionSynchronizer Utils
- * @run main ThreadStateTest
- */
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadMXBean;
-import java.lang.management.ThreadInfo;
-
-import java.util.concurrent.locks.LockSupport;
-
-public class ThreadStateTest {
- private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
-
- static class Lock {
- private String name;
- Lock(String name) {
- this.name = name;
- }
- public String toString() {
- return name;
- }
- }
- private static Lock globalLock = new Lock("my lock");
-
- public static void main(String[] argv) {
- // Force thread state initialization now before the test
- // verification begins.
- Thread.currentThread().getState();
-
- MyThread myThread = new MyThread("MyThread");
-
- // before myThread starts
- // Utils.checkThreadState(myThread, Thread.State.NEW);
-
- myThread.start();
- myThread.waitUntilStarted();
- Utils.checkThreadState(myThread, Thread.State.RUNNABLE);
- checkLockInfo(myThread, Thread.State.RUNNABLE, null, null);
-
- myThread.suspend();
- Utils.goSleep(10);
- checkSuspendedThreadState(myThread, Thread.State.RUNNABLE);
- myThread.resume();
-
- synchronized (globalLock) {
- myThread.goBlocked();
- Utils.checkThreadState(myThread, Thread.State.BLOCKED);
- checkLockInfo(myThread, Thread.State.BLOCKED,
- globalLock, Thread.currentThread());
- }
-
- myThread.goWaiting();
- Utils.checkThreadState(myThread, Thread.State.WAITING);
- checkLockInfo(myThread, Thread.State.WAITING,
- globalLock, null);
-
- myThread.goTimedWaiting();
- Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING);
- checkLockInfo(myThread, Thread.State.TIMED_WAITING,
- globalLock, null);
-
-
-
- /*
- *********** parkUntil seems not working
- * ignore this park case for now.
-
- Bug ID : 5062095
- ***********************************************
- myThread.goParked();
- Utils.checkThreadState(myThread, Thread.State.WAITING);
- checkLockInfo(myThread, Thread.State.WAITING, null, null);
-
- myThread.goTimedParked();
- Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING);
- checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null);
-
- */
-
- myThread.goSleeping();
- Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING);
- checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null);
-
-
- myThread.terminate();
- // Utils.checkThreadState(myThread, ThreadState.TERMINATED);
-
- try {
- myThread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- System.out.println("TEST FAILED: Unexpected exception.");
- throw new RuntimeException(e);
- }
- System.out.println("Test passed.");
- }
-
- private static void checkSuspendedThreadState(Thread t, Thread.State state) {
- ThreadInfo info = tm.getThreadInfo(t.getId());
- if (info == null) {
- throw new RuntimeException(t.getName() +
- " expected to have ThreadInfo " +
- " but got null.");
- }
-
- if (info.getThreadState() != state) {
- throw new RuntimeException(t.getName() + " expected to be in " +
- state + " state but got " + info.getThreadState());
- }
-
- if (!info.isSuspended()) {
- throw new RuntimeException(t.getName() + " expected to be suspended " +
- " but isSuspended() returns " + info.isSuspended());
- }
- Utils.checkThreadState(t, state);
- }
-
- private static String getLockName(Object lock) {
- if (lock == null) return null;
-
- return lock.getClass().getName() + '@' +
- Integer.toHexString(System.identityHashCode(lock));
- }
-
- private static void checkLockInfo(Thread t, Thread.State state, Object lock, Thread owner) {
- ThreadInfo info = tm.getThreadInfo(t.getId());
- if (info == null) {
- throw new RuntimeException(t.getName() +
- " expected to have ThreadInfo " +
- " but got null.");
- }
-
- if (info.getThreadState() != state) {
- throw new RuntimeException(t.getName() + " expected to be in " +
- state + " state but got " + info.getThreadState());
- }
-
- if (lock == null && info.getLockName() != null) {
- throw new RuntimeException(t.getName() +
- " expected not to be blocked on any lock" +
- " but got " + info.getLockName());
- }
- String expectedLockName = getLockName(lock);
- if (lock != null && info.getLockName() == null) {
- throw new RuntimeException(t.getName() +
- " expected to be blocked on lock [" + expectedLockName +
- "] but got null.");
- }
-
- if (lock != null && !expectedLockName.equals(info.getLockName())) {
- throw new RuntimeException(t.getName() +
- " expected to be blocked on lock [" + expectedLockName +
- "] but got [" + info.getLockName() + "].");
- }
-
- if (owner == null && info.getLockOwnerName() != null) {
- throw new RuntimeException("Lock owner is expected " +
- " to be null but got " + info.getLockOwnerName());
- }
-
- if (owner != null && info.getLockOwnerName() == null) {
- throw new RuntimeException("Lock owner is expected to be " +
- owner.getName() +
- " but got null.");
- }
- if (owner != null && !info.getLockOwnerName().equals(owner.getName())) {
- throw new RuntimeException("Lock owner is expected to be " +
- owner.getName() +
- " but got " + owner.getName());
- }
- if (owner == null && info.getLockOwnerId() != -1) {
- throw new RuntimeException("Lock owner is expected " +
- " to be -1 but got " + info.getLockOwnerId());
- }
-
- if (owner != null && info.getLockOwnerId() <= 0) {
- throw new RuntimeException("Lock owner is expected to be " +
- owner.getName() + "(id = " + owner.getId() +
- ") but got " + info.getLockOwnerId());
- }
- if (owner != null && info.getLockOwnerId() != owner.getId()) {
- throw new RuntimeException("Lock owner is expected to be " +
- owner.getName() + "(id = " + owner.getId() +
- ") but got " + info.getLockOwnerId());
- }
- if (info.isSuspended()) {
- throw new RuntimeException(t.getName() +
- " isSuspended() returns " + info.isSuspended());
- }
- }
-
- static class MyThread extends Thread {
- private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer();
-
- MyThread(String name) {
- super(name);
- }
-
- private final int RUNNABLE = 0;
- private final int BLOCKED = 1;
- private final int WAITING = 2;
- private final int TIMED_WAITING = 3;
- private final int PARKED = 4;
- private final int TIMED_PARKED = 5;
- private final int SLEEPING = 6;
- private final int TERMINATE = 7;
- private int state = RUNNABLE;
-
- private boolean done = false;
- public void run() {
- // Signal main thread to continue.
- thrsync.signal();
- while (!done) {
- switch (state) {
- case RUNNABLE: {
- double sum = 0;
- for (int i = 0; i < 1000; i++) {
- double r = Math.random();
- double x = Math.pow(3, r);
- sum += x - r;
- }
- break;
- }
- case BLOCKED: {
- // signal main thread.
- thrsync.signal();
- System.out.println(" myThread is going to block.");
- synchronized (globalLock) {
- // finish blocking
- state = RUNNABLE;
- }
- break;
- }
- case WAITING: {
- synchronized (globalLock) {
- // signal main thread.
- thrsync.signal();
- System.out.println(" myThread is going to wait.");
- try {
- globalLock.wait();
- } catch (InterruptedException e) {
- // ignore
- }
- }
- break;
- }
- case TIMED_WAITING: {
- synchronized (globalLock) {
- // signal main thread.
- thrsync.signal();
- System.out.println(" myThread is going to timed wait.");
- try {
- globalLock.wait(10000);
- } catch (InterruptedException e) {
- // ignore
- }
- }
- break;
- }
- case PARKED: {
- // signal main thread.
- thrsync.signal();
- System.out.println(" myThread is going to park.");
- LockSupport.park();
- // give a chance for the main thread to block
- System.out.println(" myThread is going to park.");
- Utils.goSleep(10);
- break;
- }
- case TIMED_PARKED: {
- // signal main thread.
- thrsync.signal();
- System.out.println(" myThread is going to timed park.");
- long deadline = System.currentTimeMillis() + 10000*1000;
- LockSupport.parkUntil(deadline);
-
- // give a chance for the main thread to block
- Utils.goSleep(10);
- break;
- }
- case SLEEPING: {
- // signal main thread.
- thrsync.signal();
- System.out.println(" myThread is going to sleep.");
- try {
- Thread.sleep(1000000);
- } catch (InterruptedException e) {
- // finish sleeping
- interrupted();
- }
- break;
- }
- case TERMINATE: {
- done = true;
- // signal main thread.
- thrsync.signal();
- break;
- }
- default:
- break;
- }
- }
- }
- public void waitUntilStarted() {
- // wait for MyThread.
- thrsync.waitForSignal();
- Utils.goSleep(10);
- }
-
- public void goBlocked() {
- System.out.println("Waiting myThread to go blocked.");
- setState(BLOCKED);
- // wait for MyThread to get blocked
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
-
- public void goWaiting() {
- System.out.println("Waiting myThread to go waiting.");
- setState(WAITING);
- // wait for MyThread to wait on object.
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
- public void goTimedWaiting() {
- System.out.println("Waiting myThread to go timed waiting.");
- setState(TIMED_WAITING);
- // wait for MyThread timed wait call.
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
- public void goParked() {
- System.out.println("Waiting myThread to go parked.");
- setState(PARKED);
- // wait for MyThread state change to PARKED.
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
- public void goTimedParked() {
- System.out.println("Waiting myThread to go timed parked.");
- setState(TIMED_PARKED);
- // wait for MyThread.
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
-
- public void goSleeping() {
- System.out.println("Waiting myThread to go sleeping.");
- setState(SLEEPING);
- // wait for MyThread.
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
- public void terminate() {
- System.out.println("Waiting myThread to terminate.");
- setState(TERMINATE);
- // wait for MyThread.
- thrsync.waitForSignal();
- Utils.goSleep(20);
- }
-
- private void setState(int newState) {
- switch (state) {
- case BLOCKED:
- while (state == BLOCKED) {
- Utils.goSleep(20);
- }
- state = newState;
- break;
- case WAITING:
- case TIMED_WAITING:
- state = newState;
- synchronized (globalLock) {
- globalLock.notify();
- }
- break;
- case PARKED:
- case TIMED_PARKED:
- state = newState;
- LockSupport.unpark(this);
- break;
- case SLEEPING:
- state = newState;
- this.interrupt();
- break;
- default:
- state = newState;
- break;
- }
- }
- }
-}
From 4f0480aaeb20f7a776917008275972f03014d5eb Mon Sep 17 00:00:00 2001
From: Mike Duigou
Date: Tue, 5 Nov 2013 19:44:41 -0800
Subject: [PATCH 021/110] 8021309: replace test/Makefile jdk_* targets with
jtreg groups 8015068: Use jtreg -exclude for handling problemList.txt
exclusions
Reviewed-by: jjg, smarks, chegar, alanb, dholmes
---
jdk/.hgignore | 1 +
jdk/test/Makefile | 471 ++++++----------------------------------------
2 files changed, 63 insertions(+), 409 deletions(-)
diff --git a/jdk/.hgignore b/jdk/.hgignore
index e849b9e6d1f..d8754b13e1f 100644
--- a/jdk/.hgignore
+++ b/jdk/.hgignore
@@ -1,5 +1,6 @@
^build/
^dist/
+^testoutput/
/nbproject/private/
^make/netbeans/.*/build/
^make/netbeans/.*/dist/
diff --git a/jdk/test/Makefile b/jdk/test/Makefile
index c4a9b93bec6..9a9092df16b 100644
--- a/jdk/test/Makefile
+++ b/jdk/test/Makefile
@@ -27,6 +27,8 @@
# Makefile to run various jdk tests
#
+.DEFAULT : all
+
# Empty these to get rid of some default rules
.SUFFIXES:
.SUFFIXES: .java
@@ -55,150 +57,19 @@ UNIQ = uniq
WC = wc
ZIP = zip
-# Get OS name from uname
-UNAME_S := $(shell $(UNAME) -s)
+# Get OS name from uname (Cygwin inexplicably adds _NT-5.1)
+UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_)
# Commands to run on paths to make mixed paths for java on windows
-GETMIXEDPATH=$(ECHO)
-
-# Location of developer shared files
-SLASH_JAVA = /java
-
-# Platform specific settings
-ifeq ($(UNAME_S), SunOS)
- OS_NAME = solaris
- OS_ARCH := $(shell $(UNAME) -p)
- OS_VERSION := $(shell $(UNAME) -r)
-endif
-ifeq ($(UNAME_S), Linux)
- OS_NAME = linux
- OS_ARCH := $(shell $(UNAME) -m)
- # Check for unknown arch, try uname -p if uname -m says unknown
- ifeq ($(OS_ARCH),unknown)
- OS_ARCH := $(shell $(UNAME) -p)
- endif
- OS_VERSION := $(shell $(UNAME) -r)
-endif
-ifeq ($(UNAME_S), Darwin)
- OS_NAME = macosx
- OS_ARCH := $(shell $(UNAME) -m)
- # Check for unknown arch, try uname -p if uname -m says unknown
- ifeq ($(OS_ARCH),unknown)
- OS_ARCH := $(shell $(UNAME) -p)
- endif
- OS_VERSION := $(shell $(UNAME) -r)
-endif
-ifeq ($(OS_NAME),)
- OS_NAME = windows
- # GNU Make or MKS overrides $(PROCESSOR_ARCHITECTURE) to always
- # return "x86". Use the first word of $(PROCESSOR_IDENTIFIER) instead.
- ifeq ($(PROCESSOR_IDENTIFIER),)
- PROC_ARCH:=$(shell $(UNAME) -m)
- else
- PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
- endif
- OS_ARCH:=$(PROC_ARCH)
+ifeq ($(UNAME_S), CYGWIN)
+ # Location of developer shared files
SLASH_JAVA = J:
- EXESUFFIX = .exe
- # These need to be different depending on MKS or CYGWIN
- ifeq ($(findstring cygdrive,$(shell ($(CD) C:/ && $(PWD)))), )
- GETMIXEDPATH = dosname -s
- OS_VERSION := $(shell $(UNAME) -r)
- else
- GETMIXEDPATH = cygpath -m -s
- OS_VERSION := $(shell $(UNAME) -s | $(CUT) -d'-' -f2)
- endif
-endif
-
-# Only want major and minor numbers from os version
-OS_VERSION := $(shell $(ECHO) "$(OS_VERSION)" | $(CUT) -d'.' -f1,2)
-
-# Name to use for x86_64 arch (historically amd64, but should change someday)
-OS_ARCH_X64_NAME:=amd64
-#OS_ARCH_X64_NAME:=x64
-
-# Alternate arch names (in case this arch is known by a second name)
-# PROBLEM_LISTS may use either name.
-OS_ARCH2-amd64:=x64
-#OS_ARCH2-x64:=amd64
-
-# Try and use the arch names consistently
-OS_ARCH:=$(patsubst x64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst X64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst AMD64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst amd64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst x86_64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst 8664,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst EM64T,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst em64t,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst intel64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst Intel64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst INTEL64,$(OS_ARCH_X64_NAME),$(OS_ARCH))
-OS_ARCH:=$(patsubst IA64,ia64,$(OS_ARCH))
-OS_ARCH:=$(patsubst X86,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst x86,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst i386,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst i486,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst i686,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst 386,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst 486,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst 586,i586,$(OS_ARCH))
-OS_ARCH:=$(patsubst 686,i586,$(OS_ARCH))
-
-# Default ARCH_DATA_MODEL settings
-ARCH_DATA_MODEL-i586 = 32
-ARCH_DATA_MODEL-$(OS_ARCH_X64_NAME) = 64
-ARCH_DATA_MODEL-ia64 = 64
-ARCH_DATA_MODEL-sparc = 32
-ARCH_DATA_MODEL-sparcv9 = 64
-
-# If ARCH_DATA_MODEL is not defined, try and pick a reasonable default
-ifndef ARCH_DATA_MODEL
- ARCH_DATA_MODEL:=$(ARCH_DATA_MODEL-$(OS_ARCH))
-endif
-ifndef ARCH_DATA_MODEL
- ARCH_DATA_MODEL=32
-endif
-
-# Platform directory name
-PLATFORM_OS = $(OS_NAME)-$(OS_ARCH)
-
-# Check ARCH_DATA_MODEL, adjust OS_ARCH accordingly on solaris
-ARCH_DATA_MODEL_ERROR= \
- ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) cannot be used with $(PLATFORM_OS)
-ifeq ($(ARCH_DATA_MODEL),64)
- ifeq ($(PLATFORM_OS),solaris-i586)
- OS_ARCH=$(OS_ARCH_X64_NAME)
- endif
- ifeq ($(PLATFORM_OS),solaris-sparc)
- OS_ARCH=sparcv9
- endif
- ifeq ($(OS_ARCH),i586)
- x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
- endif
- ifeq ($(OS_ARCH),sparc)
- x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
- endif
+ GETMIXEDPATH = cygpath -m -s
else
- ifeq ($(ARCH_DATA_MODEL),32)
- ifeq ($(OS_ARCH),$(OS_ARCH_X64_NAME))
- x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
- endif
- ifeq ($(OS_ARCH),ia64)
- x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
- endif
- ifeq ($(OS_ARCH),sparcv9)
- x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
- endif
- else
- x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
- endif
-endif
+ # Location of developer shared files
+ SLASH_JAVA = /java
-# Alternate OS_ARCH name (defaults to OS_ARCH)
-OS_ARCH2:=$(OS_ARCH2-$(OS_ARCH))
-ifeq ($(OS_ARCH2),)
- OS_ARCH2:=$(OS_ARCH)
+ GETMIXEDPATH=$(ECHO)
endif
# Root of this test area (important to use full paths in some places)
@@ -206,17 +77,18 @@ TEST_ROOT := $(shell $(PWD))
# Root of all test results
ifdef ALT_OUTPUTDIR
- ABS_OUTPUTDIR = $(ALT_OUTPUTDIR)
+ ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD))
else
- ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(PLATFORM_OS)
+ ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD))
endif
+
ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR)
ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
ifndef PRODUCT_HOME
# Try to use j2sdk-image if it exists
- ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/j2sdk-image
+ ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/j2sdk-image
PRODUCT_HOME := \
$(shell \
if [ -d $(ABS_JDK_IMAGE) ] ; then \
@@ -240,30 +112,11 @@ ifdef JPRT_PRODUCT_VM_ARGS
JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS)
endif
-# Check JAVA_ARGS arguments based on ARCH_DATA_MODEL etc.
-ifeq ($(OS_NAME),solaris)
- D64_ERROR_MESSAGE=Mismatch between ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) and use of -d64 in JAVA_ARGS=$(JAVA_ARGS)
- ifeq ($(ARCH_DATA_MODEL),32)
- ifneq ($(findstring -d64,$(JAVA_ARGS)),)
- x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)")
- endif
- endif
- ifeq ($(ARCH_DATA_MODEL),64)
- ifeq ($(findstring -d64,$(JAVA_ARGS)),)
- x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)")
- endif
- endif
-endif
-
-# Macro to run make and set the shared library permissions
-define SharedLibraryPermissions
-$(MAKE) SHARED_LIBRARY_DIR=$1 UNIQUE_DIR=$@ shared_library_permissions
-endef
-
# Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
-ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
ifdef JPRT_ARCHIVE_BUNDLE
ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
+else
+ ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
endif
# How to create the test bundle (pass or fail, we want to create this)
@@ -272,13 +125,15 @@ ZIP_UP_RESULTS = ( $(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` \
&& $(CD) $(ABS_TEST_OUTPUT_DIR) \
&& $(CHMOD) -R a+r . \
&& $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
-SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport/text/summary.txt
+
+# important results files
+SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport/text/summary.txt")
STATS_TXT_NAME = Stats.txt
-STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/$(STATS_TXT_NAME)
-RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/runlist.txt
-PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/passlist.txt
-FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/faillist.txt
-EXITCODE = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/exitcode.txt
+STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/$(STATS_TXT_NAME)")
+RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/runlist.txt")
+PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/passlist.txt")
+FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/faillist.txt")
+EXITCODE = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/exitcode.txt")
TESTEXIT = \
if [ ! -s $(EXITCODE) ] ; then \
@@ -316,8 +171,8 @@ BUNDLE_UP_AND_EXIT = \
runc="`$(CAT) $(RUNLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
passc="`$(CAT) $(PASSLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
failc="`$(CAT) $(FAILLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
- exclc="`$(CAT) $(EXCLUDELIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
- $(ECHO) "TEST STATS: name=$(UNIQUE_DIR) run=$${runc} pass=$${passc} fail=$${failc} excluded=$${exclc}" \
+ exclc="FIXME CODETOOLS-7900176"; \
+ $(ECHO) "TEST STATS: name=$(UNIQUE_DIR) run=$${runc} pass=$${passc} fail=$${failc}" \
>> $(STATS_TXT); \
else \
$(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \
@@ -336,9 +191,24 @@ all: jdk_default
@$(ECHO) "Testing completed successfully"
# Prep for output
+# Change execute permissions on shared library files.
+# Files in repositories should never have execute permissions, but
+# there are some tests that have pre-built shared libraries, and these
+# windows dll files must have execute permission. Adding execute
+# permission may happen automatically on windows when using certain
+# versions of mercurial but it cannot be guaranteed. And blindly
+# adding execute permission might be seen as a mercurial 'change', so
+# we avoid adding execute permission to repository files. But testing
+# from a plain source tree needs the chmod a+rx. Applying the chmod to
+# all shared libraries not just dll files. And with CYGWIN and sshd
+# service, you may need CYGWIN=ntsec for this to work.
prep:
@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
@$(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)`
+ @if [ ! -d $(TEST_ROOT)/../.hg ] ; then \
+ $(FIND) $(TEST_ROOT) \( -name \*.dll -o -name \*.DLL -o -name \*.so \) \
+ -exec $(CHMOD) a+rx {} \; ; \
+ fi
# Cleanup
clean:
@@ -357,50 +227,21 @@ ifndef JT_HOME
endif
endif
-# Expect JPRT to set TESTDIRS to the jtreg test dirs
-ifndef TESTDIRS
- TESTDIRS = demo
-endif
-
-# Some tests annoy me and fail frequently
-PROBLEM_LIST=ProblemList.txt
-PROBLEM_LISTS=$(PROBLEM_LIST) $(wildcard closed/$(PROBLEM_LIST))
-EXCLUDELIST=$(ABS_TEST_OUTPUT_DIR)/excludelist.txt
+# Problematic tests to be excluded
+PROBLEM_LISTS=$(call MixedDirs,$(wildcard ProblemList.txt closed/ProblemList.txt))
# Create exclude list for this platform and arch
ifdef NO_EXCLUDES
-$(EXCLUDELIST): $(PROBLEM_LISTS) $(TEST_DEPENDENCIES)
- @$(ECHO) "NOTHING_EXCLUDED" > $@
+ JTREG_EXCLUSIONS =
else
-$(EXCLUDELIST): $(PROBLEM_LISTS) $(TEST_DEPENDENCIES)
- @$(RM) $@ $@.temp1 $@.temp2
- @(($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(OS_NAME)-all' ) ;\
- ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(PLATFORM_OS)' ) ;\
- ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(OS_NAME)-$(OS_ARCH2)' ) ;\
- ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(OS_NAME)-$(OS_VERSION)') ;\
- ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- 'generic-$(OS_ARCH)' ) ;\
- ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- 'generic-$(OS_ARCH2)' ) ;\
- ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- 'generic-all' ) ;\
- ($(ECHO) "#") ;\
- ) | $(SED) -e 's@^[\ ]*@@' \
- | $(EGREP) -v '^#' > $@.temp1
- @for tdir in $(TESTDIRS) SOLARIS_10_SH_BUG_NO_EMPTY_FORS ; do \
- ( ( $(CAT) $@.temp1 | $(EGREP) "^$${tdir}" ) ; $(ECHO) "#" ) >> $@.temp2 ; \
- done
- @$(ECHO) "# at least one line" >> $@.temp2
- @( $(EGREP) -v '^#' $@.temp2 ; true ) > $@
- @$(ECHO) "Excluding list contains `$(EXPAND) $@ | $(WC) -l` items"
+ JTREG_EXCLUSIONS = $(PROBLEM_LISTS:%=-exclude:%)
endif
-# Select list of directories that exist
-define TestDirs
-$(foreach i,$1,$(wildcard ${i})) $(foreach i,$1,$(wildcard closed/${i}))
-endef
-# Running batches of tests with or without agentvm
-define RunBatch
-$(ECHO) "Running tests: $?"
-$(MAKE) TEST_DEPENDENCIES="$?" TESTDIRS="$?" UNIQUE_DIR=$@ jtreg_tests
+# convert list of directories to dos paths
+define MixedDirs
+$(foreach i,$1,$(shell $(GETMIXEDPATH) "${i}"))
endef
+
define SummaryInfo
$(ECHO) "########################################################"
$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
@@ -409,178 +250,11 @@ endef
# ------------------------------------------------------------------
-# Batches of tests (somewhat arbitrary assigments to jdk_* targets)
-# NOTE: These *do not* run the same tests as make/jprt.properties
-JDK_DEFAULT_TARGETS =
-JDK_ALL_TARGETS =
-
-JDK_ALL_TARGETS += jdk_awt
-jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt \
- javax/imageio javax/print sun/pisces)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_beans1
-JDK_DEFAULT_TARGETS += jdk_beans1
-jdk_beans1: $(call TestDirs, \
- java/beans/beancontext java/beans/PropertyChangeSupport \
- java/beans/Introspector java/beans/Performance \
- java/beans/VetoableChangeSupport java/beans/Statement)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_beans2
-jdk_beans2: $(call TestDirs, \
- java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
- java/beans/PropertyEditor)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_beans3
-jdk_beans3: $(call TestDirs, java/beans/XMLEncoder)
- $(call RunBatch)
-
-# All beans tests
-jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3
- @$(SummaryInfo)
-
-JDK_ALL_TARGETS += jdk_io
-JDK_DEFAULT_TARGETS += jdk_io
-jdk_io: $(call TestDirs, java/io)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_lang
-JDK_DEFAULT_TARGETS += jdk_lang
-jdk_lang: $(call TestDirs, java/lang sun/invoke sun/misc sun/reflect vm)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_jmx
-jdk_jmx: $(call TestDirs, javax/management com/sun/jmx)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_management
-jdk_management: $(call TestDirs, com/sun/management sun/management)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_math
-JDK_DEFAULT_TARGETS += jdk_math
-jdk_math: $(call TestDirs, java/math)
- $(call RunBatch)
-
-JDK_DEFAULT_TARGETS += jdk_time
-jdk_time: $(call TestDirs, java/time)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_other
-JDK_DEFAULT_TARGETS += jdk_other
-jdk_other: $(call TestDirs, \
- demo/jvmti demo/zipfs sample \
- javax/naming com/sun/jndi \
- javax/script \
- java/sql javax/sql \
- javax/smartcardio \
- javax/xml/jaxp \
- javax/xml/soap \
- javax/xml/ws com/sun/internal/ws com/sun/org/glassfish \
- jdk/asm \
- jdk/lambda \
- com/sun/org/apache/xerces \
- com/sun/corba \
- com/sun/tracing \
- sun/usagetracker \
- misc)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_net
-JDK_DEFAULT_TARGETS += jdk_net
-jdk_net: $(call TestDirs, com/sun/net java/net sun/net com/oracle/net)
- $(call RunBatch)
-
-jdk_nio: $(call TestDirs, java/nio sun/nio com/oracle/nio)
- $(call SharedLibraryPermissions,java/nio/channels)
- $(call RunBatch)
-
-jdk_sctp: $(call TestDirs, com/sun/nio/sctp)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_rmi
-jdk_rmi: $(call TestDirs, java/rmi sun/rmi javax/rmi/ssl)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_security1
-JDK_DEFAULT_TARGETS += jdk_security1
-jdk_security1: $(call TestDirs, java/security)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_security2
-jdk_security2: $(call TestDirs, javax/crypto javax/xml/crypto com/sun/crypto)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_security3
-jdk_security3: $(call TestDirs, com/sun/security lib/security javax/security \
- sun/security com/sun/org/apache/xml/internal/security \
- com/oracle/security)
- $(call SharedLibraryPermissions,sun/security)
- $(call RunBatch)
-
-# All security tests
-jdk_security: jdk_security1 jdk_security2 jdk_security3
- @$(SummaryInfo)
-
-JDK_ALL_TARGETS += jdk_sound
-jdk_sound: $(call TestDirs, javax/sound)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_swing
-jdk_swing: $(call TestDirs, javax/swing sun/java2d \
- demo/jfc com/sun/java/swing)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_text
-JDK_DEFAULT_TARGETS += jdk_text
-jdk_text: $(call TestDirs, java/text sun/text)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_jdi
-jdk_jdi: $(call TestDirs, com/sun/jdi)
- $(call RunBatch)
-
-JDK_ALL_TARGETS += jdk_tools
-jdk_tools: $(call TestDirs, com/sun/tools sun/jvmstat sun/tools tools)
- $(call SharedLibraryPermissions,tools/launcher)
- $(call RunBatch)
-
-ifdef OPENJDK
-jdk_jfr:
-else
-JDK_ALL_TARGETS += jdk_jfr
-jdk_jfr: $(call TestDirs, com/oracle/jfr)
- $(call RunBatch)
-endif
-
-JDK_ALL_TARGETS += jdk_util
-JDK_DEFAULT_TARGETS += jdk_util
-jdk_util: $(call TestDirs, java/util sun/util)
- $(call RunBatch)
-
-# ------------------------------------------------------------------
-
-# Run default tests
-# note that this *does not* have the same meaning as jprt.properties :: jprt.make.rule.default.test.targets
-jdk_default: $(JDK_DEFAULT_TARGETS)
- @$(SummaryInfo)
-
-# Run core tests
-# please keep this in sync with jdk/make/jprt.properties :: jprt.make.rule.core.test.targets
-jdk_core: jdk_lang jdk_math jdk_util jdk_io jdk_net jdk_nio \
- jdk_security1 jdk_security2 jdk_security3 jdk_rmi \
- jdk_management jdk_jmx jdk_text jdk_tools jdk_jfr jdk_other
- @$(SummaryInfo)
-
-# Run all tests
-# note that this *does not* have the same meaning as jprt.properties :: jprt.make.rule.all.test.targets
-jdk_all: $(JDK_ALL_TARGETS)
- @$(SummaryInfo)
-
-# These are all phony targets
-PHONY_LIST += $(JDK_ALL_TARGETS) jdk_default jdk_core jdk_all
+jdk_%:
+ $(ECHO) "Running tests: $@"
+ for each in $@; do \
+ $(MAKE) -j 1 TEST_SELECTION=":$$each" UNIQUE_DIR=$$each jtreg_tests; \
+ done
# ------------------------------------------------------------------
@@ -625,44 +299,23 @@ JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
$(JTREG): $(JT_HOME)
# Run jtreg
-jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) $(EXCLUDELIST)
- @$(EXPAND) $(EXCLUDELIST) \
- | $(CUT) -d' ' -f1 \
- | $(SED) -e 's@^@Excluding: @'
+jtreg_tests: prep $(PRODUCT_HOME) $(JTREG)
( \
( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \
export JT_HOME; \
$(shell $(GETMIXEDPATH) "$(JTREG)") \
$(JTREG_BASIC_OPTIONS) \
- -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \
- -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \
+ -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport") \
+ -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTwork") \
-jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \
- -exclude:$(shell $(GETMIXEDPATH) "$(EXCLUDELIST)") \
+ $(JTREG_EXCLUSIONS) \
$(JTREG_TEST_OPTIONS) \
- $(TESTDIRS) \
- ) ; $(BUNDLE_UP_AND_EXIT) \
+ $(TEST_SELECTION) \
+ ) ; \
+ $(BUNDLE_UP_AND_EXIT) \
) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt ; $(TESTEXIT)
-# Rule that may change execute permissions on shared library files.
-# Files in repositories should never have execute permissions, but there
-# are some tests that have pre-built shared libraries, and these windows
-# dll files must have execute permission. Adding execute permission
-# may happen automatically on windows when using certain versions of mercurial
-# but it cannot be guaranteed. And blindly adding execute permission might
-# be seen as a mercurial 'change', so we avoid adding execute permission to
-# repository files. But testing from a plain source tree needs the chmod a+rx.
-# Used on select directories and applying the chmod to all shared libraries
-# not just dll files. On windows, this may not work with MKS if the files
-# were installed with CYGWIN unzip or untar (MKS chmod may not do anything).
-# And with CYGWIN and sshd service, you may need CYGWIN=ntsec for this to work.
-#
-shared_library_permissions: $(SHARED_LIBRARY_DIR)
- if [ ! -d $(TEST_ROOT)/../.hg ] ; then \
- $(FIND) $< \( -name \*.dll -o -name \*.DLL -o -name \*.so \) \
- -exec $(CHMOD) a+rx {} \; ; \
- fi
-
-PHONY_LIST += jtreg_tests shared_library_permissions
+PHONY_LIST += jtreg_tests
################################################################
From 5eb7e21cc91150c46e0c890d2422c0951166f41f Mon Sep 17 00:00:00 2001
From: Anthony Juckel
Date: Wed, 6 Nov 2013 13:25:24 -0800
Subject: [PATCH 022/110] 8025698: (fs) Typo in exception thrown by encode() in
UnixPath.java
Reviewed-by: dxu, mduigou, henryjen, weijun
---
jdk/src/solaris/classes/sun/nio/fs/UnixPath.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
index aa04538cb20..1142b4c775b 100644
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
@@ -145,7 +145,7 @@ class UnixPath
}
if (error) {
throw new InvalidPathException(input,
- "Malformed input or input contains unmappable chacraters");
+ "Malformed input or input contains unmappable characters");
}
// trim result to actual length if required
From 23d71ee6eed0f727935ad51f8b150e185c293cb7 Mon Sep 17 00:00:00 2001
From: Eric Bruneton
Date: Wed, 6 Nov 2013 11:22:15 -0800
Subject: [PATCH 023/110] 8027227: [asm] generate CONSTANT_InterfaceMethodref
for invoke{special/static) of non-abstract methods on ifaces
Co-authored-by: Remi Forax
Co-authored-by: John Rose
Co-authored-by: Paul Sandoz
Reviewed-by: ksrini, lagergren
---
.../org/objectweb/asm/ByteVector.java | 8 +-
.../org/objectweb/asm/ClassReader.java | 23 ++---
.../org/objectweb/asm/ClassWriter.java | 23 ++++-
.../internal/org/objectweb/asm/Handle.java | 13 ++-
.../org/objectweb/asm/MethodVisitor.java | 65 +++++++++---
.../org/objectweb/asm/MethodWriter.java | 98 +++++++++++++++----
.../objectweb/asm/commons/AdviceAdapter.java | 23 ++++-
.../asm/commons/AnalyzerAdapter.java | 28 +++++-
.../asm/commons/CodeSizeEvaluator.java | 23 ++++-
.../asm/commons/GeneratorAdapter.java | 17 ++--
.../asm/commons/InstructionAdapter.java | 94 ++++++++++++++++--
.../asm/commons/JSRInlinerAdapter.java | 16 +++
.../asm/commons/LocalVariablesSorter.java | 6 ++
.../asm/commons/RemappingMethodAdapter.java | 39 +++++++-
.../commons/RemappingSignatureAdapter.java | 6 +-
.../asm/commons/SerialVersionUIDAdder.java | 9 +-
.../asm/commons/StaticInitMerger.java | 3 +-
.../asm/commons/TryCatchBlockSorter.java | 1 -
.../objectweb/asm/tree/AnnotationNode.java | 5 +
.../org/objectweb/asm/tree/ClassNode.java | 6 ++
.../org/objectweb/asm/tree/FieldNode.java | 8 +-
.../objectweb/asm/tree/MethodInsnNode.java | 35 ++++++-
.../org/objectweb/asm/tree/MethodNode.java | 38 ++++++-
.../asm/tree/TypeAnnotationNode.java | 5 +
.../objectweb/asm/tree/analysis/Frame.java | 9 ++
.../org/objectweb/asm/util/ASMifier.java | 41 +++++++-
.../objectweb/asm/util/CheckClassAdapter.java | 17 +++-
.../objectweb/asm/util/CheckFieldAdapter.java | 5 +
.../asm/util/CheckMethodAdapter.java | 71 +++++++++++---
.../org/objectweb/asm/util/Printer.java | 29 +++++-
.../org/objectweb/asm/util/Textifier.java | 28 ++++++
.../asm/util/TraceMethodVisitor.java | 26 ++++-
.../internal/org/objectweb/asm/version.txt | 12 +--
33 files changed, 711 insertions(+), 119 deletions(-)
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java
index 0d3472bcac1..89eb6d4b640 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java
@@ -233,11 +233,14 @@ public class ByteVector {
* automatically enlarged if necessary.
*
* @param s
- * a String.
+ * a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
public ByteVector putUTF8(final String s) {
int charLength = s.length();
+ if (charLength > 65535) {
+ throw new IllegalArgumentException();
+ }
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
@@ -267,6 +270,9 @@ public class ByteVector {
byteLength += 2;
}
}
+ if (byteLength > 65535) {
+ throw new IllegalArgumentException();
+ }
data[length] = (byte) (byteLength >>> 8);
data[length + 1] = (byte) byteLength;
if (length + 2 + byteLength > data.length) {
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
index 8cbc2d2c199..4f842157ac3 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
@@ -1266,7 +1266,7 @@ public class ClassReader {
u += 2;
// generates the first (implicit) stack map frame
- if (FRAMES && (stackMap != 0 || unzip)) {
+ if (FRAMES && stackMap != 0) {
/*
* for the first explicit frame the offset is not offset_delta + 1
* but only offset_delta; setting the implicit frame offset to -1
@@ -1283,8 +1283,6 @@ public class ClassReader {
if (unzip) {
getImplicitFrame(context);
}
- }
- if (FRAMES && stackMap != 0) {
/*
* Finds labels for UNINITIALIZED frame types. Instead of decoding
* each element of the stack map table, we look for 3 consecutive
@@ -1322,17 +1320,19 @@ public class ClassReader {
}
}
- // visits the frame(s) for this offset, if any
+ // visits the frame for this offset, if any
while (FRAMES && frame != null
&& (frame.offset == offset || frame.offset == -1)) {
// if there is a frame for this offset, makes the visitor visit
// it, and reads the next frame if there is one.
- if (!zip || unzip) {
- mv.visitFrame(Opcodes.F_NEW, frame.localCount, frame.local,
- frame.stackCount, frame.stack);
- } else if (frame.offset != -1) {
- mv.visitFrame(frame.mode, frame.localDiff, frame.local,
- frame.stackCount, frame.stack);
+ if (frame.offset != -1) {
+ if (!zip || unzip) {
+ mv.visitFrame(Opcodes.F_NEW, frame.localCount,
+ frame.local, frame.stackCount, frame.stack);
+ } else {
+ mv.visitFrame(frame.mode, frame.localDiff, frame.local,
+ frame.stackCount, frame.stack);
+ }
}
if (frameCount > 0) {
stackMap = readFrame(stackMap, zip, unzip, frame);
@@ -1434,6 +1434,7 @@ public class ClassReader {
case ClassWriter.FIELDORMETH_INSN:
case ClassWriter.ITFMETH_INSN: {
int cpIndex = items[readUnsignedShort(u + 1)];
+ boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
String iowner = readClass(cpIndex, c);
cpIndex = items[readUnsignedShort(cpIndex + 2)];
String iname = readUTF8(cpIndex, c);
@@ -1441,7 +1442,7 @@ public class ClassReader {
if (opcode < Opcodes.INVOKEVIRTUAL) {
mv.visitFieldInsn(opcode, iowner, iname, idesc);
} else {
- mv.visitMethodInsn(opcode, iowner, iname, idesc);
+ mv.visitMethodInsn(opcode, iowner, iname, idesc, itf);
}
if (opcode == Opcodes.INVOKEINTERFACE) {
u += 5;
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
index d5d8fa48903..ab9dcd0dce4 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
@@ -516,12 +516,12 @@ public class ClassWriter extends ClassVisitor {
* true if the maximum stack size and number of local variables
* must be automatically computed.
*/
- private final boolean computeMaxs;
+ private boolean computeMaxs;
/**
* true if the stack map frames must be recomputed from scratch.
*/
- private final boolean computeFrames;
+ private boolean computeFrames;
/**
* true if the stack map tables of this class are invalid. The
@@ -988,9 +988,22 @@ public class ClassWriter extends ClassVisitor {
attrs.put(this, null, 0, -1, -1, out);
}
if (invalidFrames) {
- ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
- new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
- return cw.toByteArray();
+ anns = null;
+ ianns = null;
+ attrs = null;
+ innerClassesCount = 0;
+ innerClasses = null;
+ bootstrapMethodsCount = 0;
+ bootstrapMethods = null;
+ firstField = null;
+ lastField = null;
+ firstMethod = null;
+ lastMethod = null;
+ computeMaxs = false;
+ computeFrames = true;
+ invalidFrames = false;
+ new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
+ return toByteArray();
}
return out.data;
}
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java
index f262f9a09a0..e8b2859b05d 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java
@@ -78,7 +78,8 @@ public final class Handle {
final int tag;
/**
- * The internal name of the field or method designed by this handle.
+ * The internal name of the class that owns the field or method designated
+ * by this handle.
*/
final String owner;
@@ -105,8 +106,8 @@ public final class Handle {
* {@link Opcodes#H_NEWINVOKESPECIAL} or
* {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner
- * the internal name of the field or method designed by this
- * handle.
+ * the internal name of the class that owns the field or method
+ * designated by this handle.
* @param name
* the name of the field or method designated by this handle.
* @param desc
@@ -135,9 +136,11 @@ public final class Handle {
}
/**
- * Returns the internal name of the field or method designed by this handle.
+ * Returns the internal name of the class that owns the field or method
+ * designated by this handle.
*
- * @return the internal name of the field or method designed by this handle.
+ * @return the internal name of the class that owns the field or method
+ * designated by this handle.
*/
public String getOwner() {
return owner;
diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java
index f21519e962c..0bb1a05b805 100644
--- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java
+++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java
@@ -68,11 +68,11 @@ package jdk.internal.org.objectweb.asm;
* visitTryCatchBlock | visitTryCatchBlockAnnotation |
* visitLocalVariable | visitLocalVariableAnnotation |
* visitLineNumber )* visitMaxs ] visitEnd. In
- * addition, the visitXInsn and visitLabel
- * methods must be called in the sequential order of the bytecode instructions
- * of the visited code, visitInsnAnnotation must be called after
- * the annotated instruction, visitTryCatchBlock must be called
- * before the labels passed as arguments have been visited,
+ * addition, the visitXInsn and visitLabel methods must
+ * be called in the sequential order of the bytecode instructions of the visited
+ * code, visitInsnAnnotation must be called after the annotated
+ * instruction, visitTryCatchBlock must be called before the
+ * labels passed as arguments have been visited,
* visitTryCatchBlockAnnotation must be called after the
* corresponding try catch block has been visited, and the
* visitLocalVariable, visitLocalVariableAnnotation and
@@ -274,13 +274,9 @@ public abstract class MethodVisitor {
* compressed form (all frames must use the same format, i.e. you must not
* mix expanded and compressed frames within a single method):
*
- *
In expanded form, all frames must have the F_NEW type, and a first
- * frame corresponding to the method signature must be explicitly visited
- * before the first instruction.
+ *
In expanded form, all frames must have the F_NEW type.
*
In compressed form, frames are basically "deltas" from the state of
- * the previous frame (the first frame, corresponding to the method's
- * parameters and access flags, is implicit in this form, and must not be
- * visited):
+ * the previous frame:
*
*
{@link Opcodes#F_SAME} representing frame with exactly the same
* locals as the previous frame and with the empty stack.
@@ -296,8 +292,14 @@ public abstract class MethodVisitor {
* same as the locals in the previous frame, except that the last 1-3 locals
* are absent and with the empty stack (nLocals is 1, 2 or 3).