--- a/hotspot/make/excludeSrc.make Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/make/excludeSrc.make Fri May 23 09:22:01 2014 -0700
@@ -77,30 +77,40 @@
CXXFLAGS += -DINCLUDE_ALL_GCS=0
CFLAGS += -DINCLUDE_ALL_GCS=0
- Src_Files_EXCLUDE += \
- cmsAdaptiveSizePolicy.cpp cmsCollectorPolicy.cpp \
- cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp compactibleFreeListSpace.cpp \
- concurrentMarkSweepGeneration.cpp concurrentMarkSweepThread.cpp \
- freeChunk.cpp adaptiveFreeList.cpp promotionInfo.cpp vmCMSOperations.cpp \
- collectionSetChooser.cpp concurrentG1Refine.cpp concurrentG1RefineThread.cpp \
- concurrentMark.cpp concurrentMarkThread.cpp dirtyCardQueue.cpp g1AllocRegion.cpp \
- g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \
- g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \
- g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \
- g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1StringDedup.cpp g1StringDedupStat.cpp \
- g1StringDedupTable.cpp g1StringDedupThread.cpp g1StringDedupQueue.cpp g1_globals.cpp heapRegion.cpp \
- g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \
- ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp g1CodeCacheRemSet.cpp \
- adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \
- cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \
- parallelScavengeHeap.cpp parMarkBitMap.cpp pcTasks.cpp psAdaptiveSizePolicy.cpp \
- psCompactionManager.cpp psGCAdaptivePolicyCounters.cpp psGenerationCounters.cpp \
- psMarkSweep.cpp psMarkSweepDecorator.cpp psMemoryPool.cpp psOldGen.cpp \
- psParallelCompact.cpp psPromotionLAB.cpp psPromotionManager.cpp psScavenge.cpp \
- psTasks.cpp psVirtualspace.cpp psYoungGen.cpp vmPSOperations.cpp asParNewGeneration.cpp \
- parCardTableModRefBS.cpp parGCAllocBuffer.cpp parNewGeneration.cpp mutableSpace.cpp \
- gSpaceCounters.cpp allocationStats.cpp spaceCounters.cpp gcAdaptivePolicyCounters.cpp \
- mutableNUMASpace.cpp immutableSpace.cpp yieldingWorkGroup.cpp hSpaceCounters.cpp
+ gc_impl := $(GAMMADIR)/src/share/vm/gc_implementation
+ gc_exclude := \
+ $(notdir $(wildcard $(gc_impl)/concurrentMarkSweep/*.cpp)) \
+ $(notdir $(wildcard $(gc_impl)/g1/*.cpp)) \
+ $(notdir $(wildcard $(gc_impl)/parallelScavenge/*.cpp)) \
+ $(notdir $(wildcard $(gc_impl)/parNew/*.cpp))
+ Src_Files_EXCLUDE += $(gc_exclude)
+
+ # Exclude everything in $(gc_impl)/shared except the files listed
+ # in $(gc_shared_keep).
+ gc_shared_all := $(notdir $(wildcard $(gc_impl)/shared/*.cpp))
+ gc_shared_keep := \
+ adaptiveSizePolicy.cpp \
+ ageTable.cpp \
+ collectorCounters.cpp \
+ cSpaceCounters.cpp \
+ gcPolicyCounters.cpp \
+ gcStats.cpp \
+ gcTimer.cpp \
+ gcTrace.cpp \
+ gcTraceSend.cpp \
+ gcTraceTime.cpp \
+ gcUtil.cpp \
+ generationCounters.cpp \
+ markSweep.cpp \
+ objectCountEventSender.cpp \
+ spaceDecorator.cpp \
+ vmGCOperations.cpp
+ Src_Files_EXCLUDE += $(filter-out $(gc_shared_keep),$(gc_shared_all))
+
+ # src/share/vm/services
+ Src_Files_EXCLUDE += \
+ g1MemoryPool.cpp \
+ psMemoryPool.cpp
endif
ifeq ($(INCLUDE_NMT), false)
--- a/hotspot/src/os/windows/vm/os_windows.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri May 23 09:22:01 2014 -0700
@@ -5005,7 +5005,11 @@
// wrong; at these points, eax contains the address of the offending block (I think).
// To get to the exlicit error message(s) below, just continue twice.
HANDLE heap = GetProcessHeap();
- { HeapLock(heap);
+
+ // If we fail to lock the heap, then gflags.exe has been used
+ // or some other special heap flag has been set that prevents
+ // locking. We don't try to walk a heap we can't lock.
+ if (HeapLock(heap) != 0) {
PROCESS_HEAP_ENTRY phe;
phe.lpData = NULL;
while (HeapWalk(heap, &phe) != 0) {
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri May 23 09:22:01 2014 -0700
@@ -158,6 +158,9 @@
void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) {
clear_bits(vars, _arg_local);
+ if (vars.contains_allocated()) {
+ _allocated_escapes = true;
+ }
}
void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri May 23 09:22:01 2014 -0700
@@ -2805,7 +2805,7 @@
"Short length on BootstrapMethods in class file %s",
CHECK);
- guarantee_property(attribute_byte_length > sizeof(u2),
+ guarantee_property(attribute_byte_length >= sizeof(u2),
"Invalid BootstrapMethods attribute length %u in class file %s",
attribute_byte_length,
CHECK);
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri May 23 09:22:01 2014 -0700
@@ -549,6 +549,8 @@
ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL;
+bool ClassLoaderDataGraph::_should_purge = false;
+
// Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous, TRAPS) {
@@ -675,32 +677,6 @@
return array;
}
-// For profiling and hsfind() only. Otherwise, this is unsafe (and slow). This
-// is done lock free to avoid lock inversion problems. It is safe because
-// new ClassLoaderData are added to the end of the CLDG, and only removed at
-// safepoint. The _unloading list can be deallocated concurrently with CMS so
-// this doesn't look in metaspace for classes that have been unloaded.
-bool ClassLoaderDataGraph::contains(const void* x) {
- if (DumpSharedSpaces) {
- // There are only two metaspaces to worry about.
- ClassLoaderData* ncld = ClassLoaderData::the_null_class_loader_data();
- return (ncld->ro_metaspace()->contains(x) || ncld->rw_metaspace()->contains(x));
- }
-
- if (UseSharedSpaces && MetaspaceShared::is_in_shared_space(x)) {
- return true;
- }
-
- for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
- if (cld->metaspace_or_null() != NULL && cld->metaspace_or_null()->contains(x)) {
- return true;
- }
- }
-
- // Do not check unloading list because deallocation can be concurrent.
- return false;
-}
-
#ifndef PRODUCT
bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
@@ -759,6 +735,7 @@
}
void ClassLoaderDataGraph::purge() {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
ClassLoaderData* list = _unloading;
_unloading = NULL;
ClassLoaderData* next = list;
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri May 23 09:22:01 2014 -0700
@@ -66,6 +66,7 @@
static ClassLoaderData* _unloading;
// CMS support.
static ClassLoaderData* _saved_head;
+ static bool _should_purge;
static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS);
static void post_class_unload_events(void);
@@ -87,12 +88,20 @@
static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
static GrowableArray<ClassLoaderData*>* new_clds();
+ static void set_should_purge(bool b) { _should_purge = b; }
+ static void purge_if_needed() {
+ // Only purge the CLDG for CMS if concurrent sweep is complete.
+ if (_should_purge) {
+ purge();
+ // reset for next time.
+ set_should_purge(false);
+ }
+ }
+
static void dump_on(outputStream * const out) PRODUCT_RETURN;
static void dump() { dump_on(tty); }
static void verify();
- // expensive test for pointer in metaspace for debugging
- static bool contains(const void* x);
#ifndef PRODUCT
static bool contains_loader_data(ClassLoaderData* loader_data);
#endif
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri May 23 09:22:01 2014 -0700
@@ -604,7 +604,6 @@
Ticks class_load_start_time = Ticks::now();
- // UseNewReflection
// Fix for 4474172; see evaluation for more details
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
@@ -898,7 +897,6 @@
Handle protection_domain,
TRAPS) {
- // UseNewReflection
// The result of this call should be consistent with the result
// of the call to resolve_instance_class_or_null().
// See evaluation 6790209 and 4474172 for more details.
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri May 23 09:22:01 2014 -0700
@@ -390,7 +390,7 @@
return k;
}
static Klass* check_klass_Opt_Only_JDK14NewRef(Klass* k) {
- assert(JDK_Version::is_gte_jdk14x_version() && UseNewReflection, "JDK 1.4 only");
+ assert(JDK_Version::is_gte_jdk14x_version(), "JDK 1.4 only");
// despite the optional loading, if you use this it must be present:
return check_klass(k);
}
--- a/hotspot/src/share/vm/classfile/verifier.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Fri May 23 09:22:01 2014 -0700
@@ -211,9 +211,9 @@
// reflection implementation, not just those associated with
// sun/reflect/SerializationConstructorAccessor.
// NOTE: this is called too early in the bootstrapping process to be
- // guarded by Universe::is_gte_jdk14x_version()/UseNewReflection.
+ // guarded by Universe::is_gte_jdk14x_version().
// Also for lambda generated code, gte jdk8
- (!is_reflect || VerifyReflectionBytecodes));
+ (!is_reflect));
}
Symbol* Verifier::inference_verify(
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp Fri May 23 09:22:01 2014 -0700
@@ -86,7 +86,7 @@
{
// Match "jvm[^/]*" in jvm_path.
const char* base = buf;
- const char* p = strrchr(buf, '/');
+ const char* p = strrchr(buf, *os::file_separator());
if (p != NULL) lib_offset = p - base + 1;
p = strstr(p ? p : base, "jvm");
if (p != NULL) jvm_offset = p - base;
@@ -111,7 +111,7 @@
if (_library == NULL) {
// 3. <home>/jre/lib/<arch>/hsdis-<arch>.so
buf[lib_offset - 1] = '\0';
- const char* p = strrchr(buf, '/');
+ const char* p = strrchr(buf, *os::file_separator());
if (p != NULL) {
lib_offset = p - buf + 1;
strcpy(&buf[lib_offset], hsdis_library_name);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri May 23 09:22:01 2014 -0700
@@ -6362,7 +6362,9 @@
verify_overflow_empty();
if (should_unload_classes()) {
- ClassLoaderDataGraph::purge();
+ // Delay purge to the beginning of the next safepoint. Metaspace::contains
+ // requires that the virtual spaces are stable and not deleted.
+ ClassLoaderDataGraph::set_should_purge(true);
}
_intra_sweep_timer.stop();
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri May 23 09:22:01 2014 -0700
@@ -820,7 +820,7 @@
// false before we start remark. At this point we should also be
// in a STW phase.
assert(!concurrent_marking_in_progress(), "invariant");
- assert(_finger == _heap_end,
+ assert(out_of_regions(),
err_msg("only way to get here: _finger: "PTR_FORMAT", _heap_end: "PTR_FORMAT,
p2i(_finger), p2i(_heap_end)));
update_g1_committed(true);
@@ -979,7 +979,9 @@
if (concurrent()) {
SuspendibleThreadSet::leave();
}
- _first_overflow_barrier_sync.enter();
+
+ bool barrier_aborted = !_first_overflow_barrier_sync.enter();
+
if (concurrent()) {
SuspendibleThreadSet::join();
}
@@ -987,7 +989,17 @@
// more work
if (verbose_low()) {
- gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id);
+ if (barrier_aborted) {
+ gclog_or_tty->print_cr("[%u] aborted first barrier", worker_id);
+ } else {
+ gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id);
+ }
+ }
+
+ if (barrier_aborted) {
+ // If the barrier aborted we ignore the overflow condition and
+ // just abort the whole marking phase as quickly as possible.
+ return;
}
// If we're executing the concurrent phase of marking, reset the marking
@@ -1027,14 +1039,20 @@
if (concurrent()) {
SuspendibleThreadSet::leave();
}
- _second_overflow_barrier_sync.enter();
+
+ bool barrier_aborted = !_second_overflow_barrier_sync.enter();
+
if (concurrent()) {
SuspendibleThreadSet::join();
}
// at this point everything should be re-initialized and ready to go
if (verbose_low()) {
- gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id);
+ if (barrier_aborted) {
+ gclog_or_tty->print_cr("[%u] aborted second barrier", worker_id);
+ } else {
+ gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id);
+ }
}
}
@@ -3241,6 +3259,8 @@
for (uint i = 0; i < _max_worker_id; ++i) {
_tasks[i]->clear_region_fields();
}
+ _first_overflow_barrier_sync.abort();
+ _second_overflow_barrier_sync.abort();
_has_aborted = true;
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri May 23 09:22:01 2014 -0700
@@ -542,8 +542,12 @@
// frequently.
HeapRegion* claim_region(uint worker_id);
- // It determines whether we've run out of regions to scan
- bool out_of_regions() { return _finger == _heap_end; }
+ // It determines whether we've run out of regions to scan. Note that
+ // the finger can point past the heap end in case the heap was expanded
+ // to satisfy an allocation without doing a GC. This is fine, because all
+ // objects in those regions will be considered live anyway because of
+ // SATB guarantees (i.e. their TAMS will be equal to bottom).
+ bool out_of_regions() { return _finger >= _heap_end; }
// Returns the task with the given id
CMTask* task(int id) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri May 23 09:22:01 2014 -0700
@@ -5402,7 +5402,7 @@
if (_g1h->is_in_g1_reserved(p)) {
_par_scan_state->push_on_queue(p);
} else {
- assert(!ClassLoaderDataGraph::contains((address)p),
+ assert(!Metaspace::contains((const void*)p),
err_msg("Otherwise need to call _copy_metadata_obj_cl->do_oop(p) "
PTR_FORMAT, p));
_copy_non_heap_obj_cl->do_oop(p);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Fri May 23 09:22:01 2014 -0700
@@ -96,7 +96,15 @@
jbyte *const first = byte_for(mr.start());
jbyte *const last = byte_after(mr.last());
- memset(first, g1_young_gen, last - first);
+ // Below we may use an explicit loop instead of memset() because on
+ // certain platforms memset() can give concurrent readers phantom zeros.
+ if (UseMemSetInBOT) {
+ memset(first, g1_young_gen, last - first);
+ } else {
+ for (jbyte* i = first; i < last; i++) {
+ *i = g1_young_gen;
+ }
+ }
}
#ifndef PRODUCT
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Fri May 23 09:22:01 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -194,23 +194,16 @@
}
bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) {
- int ind = (int) (region_ind & capacity_mask());
- int cur_ind = _buckets[ind];
- SparsePRTEntry* cur;
- while (cur_ind != NullEntry &&
- (cur = entry(cur_ind))->r_ind() != region_ind) {
- cur_ind = cur->next_index();
+ SparsePRTEntry* entry = get_entry(region_ind);
+ if (entry == NULL) {
+ return false;
}
-
- if (cur_ind == NullEntry) return false;
// Otherwise...
- assert(cur->r_ind() == region_ind, "Postcondition of loop + test above.");
- assert(cur->num_valid_cards() > 0, "Inv");
- cur->copy_cards(cards);
+ entry->copy_cards(cards);
return true;
}
-SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) {
+SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) const {
int ind = (int) (region_ind & capacity_mask());
int cur_ind = _buckets[ind];
SparsePRTEntry* cur;
@@ -247,27 +240,8 @@
}
SparsePRTEntry*
-RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const {
- assert(occupied_entries() < capacity(), "Precondition");
- int ind = (int) (region_ind & capacity_mask());
- int cur_ind = _buckets[ind];
- SparsePRTEntry* cur;
- while (cur_ind != NullEntry &&
- (cur = entry(cur_ind))->r_ind() != region_ind) {
- cur_ind = cur->next_index();
- }
-
- if (cur_ind != NullEntry) {
- assert(cur->r_ind() == region_ind, "Loop postcondition + test");
- return cur;
- } else {
- return NULL;
- }
-}
-
-SparsePRTEntry*
RSHashTable::entry_for_region_ind_create(RegionIdx_t region_ind) {
- SparsePRTEntry* res = entry_for_region_ind(region_ind);
+ SparsePRTEntry* res = get_entry(region_ind);
if (res == NULL) {
int new_ind = alloc_entry();
assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room.");
@@ -365,7 +339,7 @@
}
bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const {
- SparsePRTEntry* e = entry_for_region_ind(region_index);
+ SparsePRTEntry* e = get_entry(region_index);
return (e != NULL && e->contains_card(card_index));
}
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Fri May 23 09:22:01 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,12 +122,6 @@
// Requires that the caller hold a lock preventing parallel modifying
// operations, and that the the table be less than completely full. If
// an entry for "region_ind" is already in the table, finds it and
- // returns its address; otherwise returns "NULL."
- SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
-
- // Requires that the caller hold a lock preventing parallel modifying
- // operations, and that the the table be less than completely full. If
- // an entry for "region_ind" is already in the table, finds it and
// returns its address; otherwise allocates, initializes, inserts and
// returns a new entry for "region_ind".
SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
@@ -158,7 +152,7 @@
void add_entry(SparsePRTEntry* e);
- SparsePRTEntry* get_entry(RegionIdx_t region_id);
+ SparsePRTEntry* get_entry(RegionIdx_t region_id) const;
void clear();
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri May 23 09:22:01 2014 -0700
@@ -950,7 +950,6 @@
// reflection implementation, not just those associated with
// sun/reflect/SerializationConstructorAccessor.
bool is_reflect = JDK_Version::is_gte_jdk14x_version() &&
- UseNewReflection &&
klass_to_check->is_subclass_of(
SystemDictionary::reflect_MagicAccessorImpl_klass());
--- a/hotspot/src/share/vm/memory/allocation.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/memory/allocation.cpp Fri May 23 09:22:01 2014 -0700
@@ -75,7 +75,7 @@
}
bool MetaspaceObj::is_metaspace_object() const {
- return ClassLoaderDataGraph::contains((void*)this);
+ return Metaspace::contains((void*)this);
}
void MetaspaceObj::print_address_on(outputStream* st) const {
--- a/hotspot/src/share/vm/memory/metaspace.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Fri May 23 09:22:01 2014 -0700
@@ -316,6 +316,8 @@
MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); }
MetaWord* end() const { return (MetaWord*) _virtual_space.high(); }
+ bool contains(const void* ptr) { return ptr >= low() && ptr < high(); }
+
size_t reserved_words() const { return _virtual_space.reserved_size() / BytesPerWord; }
size_t committed_words() const { return _virtual_space.actual_committed_size() / BytesPerWord; }
@@ -557,6 +559,8 @@
void inc_virtual_space_count();
void dec_virtual_space_count();
+ bool contains(const void* ptr);
+
// Unlink empty VirtualSpaceNodes and free it.
void purge(ChunkManager* chunk_manager);
@@ -641,8 +645,6 @@
// Accessors
Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; }
void set_chunks_in_use(ChunkIndex index, Metachunk* v) {
- // ensure lock-free iteration sees fully initialized node
- OrderAccess::storestore();
_chunks_in_use[index] = v;
}
@@ -757,8 +759,6 @@
void print_on(outputStream* st) const;
void locked_print_chunks_in_use_on(outputStream* st) const;
- bool contains(const void *ptr);
-
void verify();
void verify_chunk_size(Metachunk* chunk);
NOT_PRODUCT(void mangle_freed_chunks();)
@@ -1078,6 +1078,7 @@
// nodes with a 0 container_count. Remove Metachunks in
// the node from their respective freelists.
void VirtualSpaceList::purge(ChunkManager* chunk_manager) {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint for contains to work");
assert_lock_strong(SpaceManager::expand_lock());
// Don't use a VirtualSpaceListIterator because this
// list is being changed and a straightforward use of an iterator is not safe.
@@ -1111,8 +1112,8 @@
}
#ifdef ASSERT
if (purged_vsl != NULL) {
- // List should be stable enough to use an iterator here.
- VirtualSpaceListIterator iter(virtual_space_list());
+ // List should be stable enough to use an iterator here.
+ VirtualSpaceListIterator iter(virtual_space_list());
while (iter.repeat()) {
VirtualSpaceNode* vsl = iter.get_next();
assert(vsl != purged_vsl, "Purge of vsl failed");
@@ -1121,6 +1122,23 @@
#endif
}
+
+// This function looks at the mmap regions in the metaspace without locking.
+// The chunks are added with store ordering and not deleted except for at
+// unloading time during a safepoint.
+bool VirtualSpaceList::contains(const void* ptr) {
+ // List should be stable enough to use an iterator here because removing virtual
+ // space nodes is only allowed at a safepoint.
+ VirtualSpaceListIterator iter(virtual_space_list());
+ while (iter.repeat()) {
+ VirtualSpaceNode* vsn = iter.get_next();
+ if (vsn->contains(ptr)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void VirtualSpaceList::retire_current_virtual_space() {
assert_lock_strong(SpaceManager::expand_lock());
@@ -1210,6 +1228,8 @@
} else {
assert(new_entry->reserved_words() == vs_word_size,
"Reserved memory size differs from requested memory size");
+ // ensure lock-free iteration sees fully initialized node
+ OrderAccess::storestore();
link_vs(new_entry);
return true;
}
@@ -2434,21 +2454,6 @@
return result;
}
-// This function looks at the chunks in the metaspace without locking.
-// The chunks are added with store ordering and not deleted except for at
-// unloading time.
-bool SpaceManager::contains(const void *ptr) {
- for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i))
- {
- Metachunk* curr = chunks_in_use(i);
- while (curr != NULL) {
- if (curr->contains(ptr)) return true;
- curr = curr->next();
- }
- }
- return false;
-}
-
void SpaceManager::verify() {
// If there are blocks in the dictionary, then
// verification of chunks does not work since
@@ -3538,11 +3543,15 @@
}
bool Metaspace::contains(const void* ptr) {
- if (vsm()->contains(ptr)) return true;
- if (using_class_space()) {
- return class_vsm()->contains(ptr);
+ if (UseSharedSpaces && MetaspaceShared::is_in_shared_space(ptr)) {
+ return true;
}
- return false;
+
+ if (using_class_space() && get_space_list(ClassType)->contains(ptr)) {
+ return true;
+ }
+
+ return get_space_list(NonClassType)->contains(ptr);
}
void Metaspace::verify() {
@@ -3787,5 +3796,4 @@
TestVirtualSpaceNodeTest::test();
TestVirtualSpaceNodeTest::test_is_available();
}
-
#endif
--- a/hotspot/src/share/vm/memory/metaspace.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/memory/metaspace.hpp Fri May 23 09:22:01 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -232,7 +232,8 @@
MetaWord* expand_and_allocate(size_t size,
MetadataType mdtype);
- bool contains(const void* ptr);
+ static bool contains(const void* ptr);
+
void dump(outputStream* const out) const;
// Free empty virtualspaces
--- a/hotspot/src/share/vm/oops/cpCache.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/oops/cpCache.cpp Fri May 23 09:22:01 2014 -0700
@@ -498,9 +498,10 @@
// _f1 == NULL || !_f1->is_method() are OK here
return true;
}
- // return false if _f1 refers to an old or an obsolete method
+ // return false if _f1 refers to a non-deleted old or obsolete method
return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
- !((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete());
+ (f1_as_method()->is_deleted() ||
+ (!f1_as_method()->is_old() && !f1_as_method()->is_obsolete())));
}
bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
--- a/hotspot/src/share/vm/oops/klass.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/oops/klass.cpp Fri May 23 09:22:01 2014 -0700
@@ -640,7 +640,7 @@
// This can be expensive, but it is worth checking that this klass is actually
// in the CLD graph but not in production.
- assert(ClassLoaderDataGraph::contains((address)this), "Should be");
+ assert(Metaspace::contains((address)this), "Should be");
guarantee(this->is_klass(),"should be klass");
--- a/hotspot/src/share/vm/oops/method.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/oops/method.cpp Fri May 23 09:22:01 2014 -0700
@@ -1019,13 +1019,11 @@
* security related stack walks (like Reflection.getCallerClass).
*/
bool Method::is_ignored_by_security_stack_walk() const {
- const bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection;
-
if (intrinsic_id() == vmIntrinsics::_invoke) {
// This is Method.invoke() -- ignore it
return true;
}
- if (use_new_reflection &&
+ if (JDK_Version::is_gte_jdk14x_version() &&
method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) {
// This is an auxilary frame -- ignore it
return true;
@@ -1868,6 +1866,14 @@
loader_data->jmethod_ids()->clear_all_methods();
}
+bool Method::has_method_vptr(const void* ptr) {
+ Method m;
+ // This assumes that the vtbl pointer is the first word of a C++ object.
+ // This assumption is also in universe.cpp patch_klass_vtble
+ void* vtbl2 = dereference_vptr((const void*)&m);
+ void* this_vtbl = dereference_vptr(ptr);
+ return vtbl2 == this_vtbl;
+}
// Check that this pointer is valid by checking that the vtbl pointer matches
bool Method::is_valid_method() const {
@@ -1876,12 +1882,7 @@
} else if (!is_metaspace_object()) {
return false;
} else {
- Method m;
- // This assumes that the vtbl pointer is the first word of a C++ object.
- // This assumption is also in universe.cpp patch_klass_vtble
- void* vtbl2 = dereference_vptr((void*)&m);
- void* this_vtbl = dereference_vptr((void*)this);
- return vtbl2 == this_vtbl;
+ return has_method_vptr((const void*)this);
}
}
--- a/hotspot/src/share/vm/oops/method.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/oops/method.hpp Fri May 23 09:22:01 2014 -0700
@@ -684,6 +684,8 @@
void set_is_old() { _access_flags.set_is_old(); }
bool is_obsolete() const { return access_flags().is_obsolete(); }
void set_is_obsolete() { _access_flags.set_is_obsolete(); }
+ bool is_deleted() const { return access_flags().is_deleted(); }
+ void set_is_deleted() { _access_flags.set_is_deleted(); }
bool on_stack() const { return access_flags().on_stack(); }
void set_on_stack(const bool value);
@@ -876,6 +878,7 @@
const char* internal_name() const { return "{method}"; }
// Check for valid method pointer
+ static bool has_method_vptr(const void* ptr);
bool is_valid_method() const;
// Verify
--- a/hotspot/src/share/vm/opto/library_call.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri May 23 09:22:01 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -420,7 +420,6 @@
return NULL;
case vmIntrinsics::_getCallerClass:
- if (!UseNewReflection) return NULL;
if (!InlineReflectionGetCallerClass) return NULL;
if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL;
break;
--- a/hotspot/src/share/vm/prims/jni.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/prims/jni.cpp Fri May 23 09:22:01 2014 -0700
@@ -544,7 +544,7 @@
if (m->is_initializer()) {
reflection_method = Reflection::new_constructor(m, CHECK_NULL);
} else {
- reflection_method = Reflection::new_method(m, UseNewReflection, false, CHECK_NULL);
+ reflection_method = Reflection::new_method(m, false, CHECK_NULL);
}
ret = JNIHandles::make_local(env, reflection_method);
return ret;
@@ -2272,7 +2272,7 @@
found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, &fd);
}
assert(found, "bad fieldID passed into jni_ToReflectedField");
- oop reflected = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);
+ oop reflected = Reflection::new_field(&fd, CHECK_NULL);
ret = JNIHandles::make_local(env, reflected);
return ret;
JNI_END
--- a/hotspot/src/share/vm/prims/jvm.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/prims/jvm.cpp Fri May 23 09:22:01 2014 -0700
@@ -1854,7 +1854,7 @@
if (!publicOnly || fs.access_flags().is_public()) {
fd.reinitialize(k(), fs.index());
- oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL);
+ oop field = Reflection::new_field(&fd, CHECK_NULL);
result->obj_at_put(out_idx, field);
++out_idx;
}
@@ -1932,7 +1932,7 @@
if (want_constructor) {
m = Reflection::new_constructor(method, CHECK_NULL);
} else {
- m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL);
+ m = Reflection::new_method(method, false, CHECK_NULL);
}
result->obj_at_put(i, m);
}
@@ -2055,7 +2055,7 @@
}
oop method;
if (!m->is_initializer() || m->is_static()) {
- method = Reflection::new_method(m, true, true, CHECK_NULL);
+ method = Reflection::new_method(m, true, CHECK_NULL);
} else {
method = Reflection::new_constructor(m, CHECK_NULL);
}
@@ -2105,7 +2105,7 @@
if (target_klass == NULL) {
THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class");
}
- oop field = Reflection::new_field(&fd, true, CHECK_NULL);
+ oop field = Reflection::new_field(&fd, CHECK_NULL);
return JNIHandles::make_local(field);
}
@@ -3521,7 +3521,6 @@
JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env))
for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
- // UseNewReflection
vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection
oop loader = vfst.method()->method_holder()->class_loader();
if (loader != NULL) {
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri May 23 09:22:01 2014 -0700
@@ -2970,7 +2970,8 @@
assert(!old_method->has_vtable_index(),
"cannot delete methods with vtable entries");;
- // Mark all deleted methods as old and obsolete
+ // Mark all deleted methods as old, obsolete and deleted
+ old_method->set_is_deleted();
old_method->set_is_old();
old_method->set_is_obsolete();
++obsolete_count;
@@ -3576,7 +3577,7 @@
no_old_methods = false;
}
- // the constant pool cache should never contain old or obsolete methods
+ // the constant pool cache should never contain non-deleted old or obsolete methods
if (ik->constants() != NULL &&
ik->constants()->cache() != NULL &&
!ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri May 23 09:22:01 2014 -0700
@@ -312,6 +312,9 @@
{ "DefaultThreadPriority", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "NoYieldsInMicrolock", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "BackEdgeThreshold", JDK_Version::jdk(9), JDK_Version::jdk(10) },
+ { "UseNewReflection", JDK_Version::jdk(9), JDK_Version::jdk(10) },
+ { "ReflectionWrapResolutionErrors",JDK_Version::jdk(9), JDK_Version::jdk(10) },
+ { "VerifyReflectionBytecodes", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ NULL, JDK_Version(0), JDK_Version(0) }
};
@@ -581,11 +584,20 @@
// Parses a memory size specification string.
static bool atomull(const char *s, julong* result) {
julong n = 0;
- int args_read = sscanf(s, JULONG_FORMAT, &n);
+ int args_read = 0;
+ bool is_hex = false;
+ // Skip leading 0[xX] for hexadecimal
+ if (*s =='0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
+ s += 2;
+ is_hex = true;
+ args_read = sscanf(s, JULONG_FORMAT_X, &n);
+ } else {
+ args_read = sscanf(s, JULONG_FORMAT, &n);
+ }
if (args_read != 1) {
return false;
}
- while (*s != '\0' && isdigit(*s)) {
+ while (*s != '\0' && (isdigit(*s) || (is_hex && isxdigit(*s)))) {
s++;
}
// 4705540: illegal if more characters are found after the first non-digit
@@ -779,7 +791,7 @@
}
}
-#define VALUE_RANGE "[-kmgtKMGT0123456789]"
+#define VALUE_RANGE "[-kmgtxKMGTX0123456789abcdefABCDEF]"
if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "=" "%" XSTR(BUFLEN) VALUE_RANGE "%c", name, value, &dummy) == 2) {
return set_numeric_flag(name, value, origin);
}
--- a/hotspot/src/share/vm/runtime/globals.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri May 23 09:22:01 2014 -0700
@@ -3656,22 +3656,6 @@
\
/* New JDK 1.4 reflection implementation */ \
\
- develop(bool, UseNewReflection, true, \
- "Temporary flag for transition to reflection based on dynamic " \
- "bytecode generation in 1.4; can no longer be turned off in 1.4 " \
- "JDK, and is unneeded in 1.3 JDK, but marks most places VM " \
- "changes were needed") \
- \
- develop(bool, VerifyReflectionBytecodes, false, \
- "Force verification of 1.4 reflection bytecodes. Does not work " \
- "in situations like that described in 4486457 or for " \
- "constructors generated for serialization, so can not be enabled "\
- "in product.") \
- \
- product(bool, ReflectionWrapResolutionErrors, true, \
- "Temporary flag for transition to AbstractMethodError wrapped " \
- "in InvocationTargetException. See 6531596") \
- \
develop(intx, FastSuperclassLimit, 8, \
"Depth of hardwired instanceof accelerator array") \
\
--- a/hotspot/src/share/vm/runtime/os.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/os.cpp Fri May 23 09:22:01 2014 -0700
@@ -1097,11 +1097,15 @@
}
- // Check if in metaspace.
- if (ClassLoaderDataGraph::contains((address)addr)) {
- // Use addr->print() from the debugger instead (not here)
- st->print_cr(INTPTR_FORMAT
- " is pointing into metadata", addr);
+ // Check if in metaspace and print types that have vptrs (only method now)
+ if (Metaspace::contains(addr)) {
+ if (Method::has_method_vptr((const void*)addr)) {
+ ((Method*)addr)->print_value_on(st);
+ st->cr();
+ } else {
+ // Use addr->print() from the debugger instead (not here)
+ st->print_cr(INTPTR_FORMAT " is pointing into metadata", addr);
+ }
return;
}
--- a/hotspot/src/share/vm/runtime/reflection.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Fri May 23 09:22:01 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -466,7 +466,6 @@
// New (1.4) reflection implementation. Allow all accesses from
// sun/reflect/MagicAccessorImpl subclasses to succeed trivially.
if ( JDK_Version::is_gte_jdk14x_version()
- && UseNewReflection
&& current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
return true;
}
@@ -571,7 +570,6 @@
// New (1.4) reflection implementation. Allow all accesses from
// sun/reflect/MagicAccessorImpl subclasses to succeed trivially.
if ( JDK_Version::is_gte_jdk14x_version()
- && UseNewReflection
&& current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
return true;
}
@@ -708,7 +706,7 @@
}
-oop Reflection::new_method(methodHandle method, bool intern_name, bool for_constant_pool_access, TRAPS) {
+oop Reflection::new_method(methodHandle method, bool for_constant_pool_access, TRAPS) {
// In jdk1.2.x, getMethods on an interface erroneously includes <clinit>, thus the complicated assert.
// Also allow sun.reflect.ConstantPool to refer to <clinit> methods as java.lang.reflect.Methods.
assert(!method()->is_initializer() ||
@@ -731,14 +729,8 @@
if (exception_types.is_null()) return NULL;
Symbol* method_name = method->name();
- Handle name;
- if (intern_name) {
- // intern_name is only true with UseNewReflection
- oop name_oop = StringTable::intern(method_name, CHECK_NULL);
- name = Handle(THREAD, name_oop);
- } else {
- name = java_lang_String::create_from_symbol(method_name, CHECK_NULL);
- }
+ oop name_oop = StringTable::intern(method_name, CHECK_NULL);
+ Handle name = Handle(THREAD, name_oop);
if (name == NULL) return NULL;
int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
@@ -825,16 +817,10 @@
}
-oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) {
+oop Reflection::new_field(fieldDescriptor* fd, TRAPS) {
Symbol* field_name = fd->name();
- Handle name;
- if (intern_name) {
- // intern_name is only true with UseNewReflection
- oop name_oop = StringTable::intern(field_name, CHECK_NULL);
- name = Handle(THREAD, name_oop);
- } else {
- name = java_lang_String::create_from_symbol(field_name, CHECK_NULL);
- }
+ oop name_oop = StringTable::intern(field_name, CHECK_NULL);
+ Handle name = Handle(THREAD, name_oop);
Symbol* signature = fd->signature();
instanceKlassHandle holder (THREAD, fd->field_holder());
Handle type = new_type(signature, holder, CHECK_NULL);
@@ -933,27 +919,23 @@
// resolve based on the receiver
if (reflected_method->method_holder()->is_interface()) {
// resolve interface call
- if (ReflectionWrapResolutionErrors) {
- // new default: 6531596
- // Match resolution errors with those thrown due to reflection inlining
- // Linktime resolution & IllegalAccessCheck already done by Class.getMethod()
- method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD);
- if (HAS_PENDING_EXCEPTION) {
- // Method resolution threw an exception; wrap it in an InvocationTargetException
- oop resolution_exception = PENDING_EXCEPTION;
- CLEAR_PENDING_EXCEPTION;
- // JVMTI has already reported the pending exception
- // JVMTI internal flag reset is needed in order to report InvocationTargetException
- if (THREAD->is_Java_thread()) {
- JvmtiExport::clear_detected_exception((JavaThread*) THREAD);
- }
- JavaCallArguments args(Handle(THREAD, resolution_exception));
- THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
- vmSymbols::throwable_void_signature(),
- &args);
+ //
+ // Match resolution errors with those thrown due to reflection inlining
+ // Linktime resolution & IllegalAccessCheck already done by Class.getMethod()
+ method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ // Method resolution threw an exception; wrap it in an InvocationTargetException
+ oop resolution_exception = PENDING_EXCEPTION;
+ CLEAR_PENDING_EXCEPTION;
+ // JVMTI has already reported the pending exception
+ // JVMTI internal flag reset is needed in order to report InvocationTargetException
+ if (THREAD->is_Java_thread()) {
+ JvmtiExport::clear_detected_exception((JavaThread*) THREAD);
}
- } else {
- method = resolve_interface_call(klass, reflected_method, target_klass, receiver, CHECK_(NULL));
+ JavaCallArguments args(Handle(THREAD, resolution_exception));
+ THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
+ vmSymbols::throwable_void_signature(),
+ &args);
}
} else {
// if the method can be overridden, we resolve using the vtable index.
@@ -970,24 +952,16 @@
// Check for abstract methods as well
if (method->is_abstract()) {
// new default: 6531596
- if (ReflectionWrapResolutionErrors) {
- ResourceMark rm(THREAD);
- Handle h_origexception = Exceptions::new_exception(THREAD,
- vmSymbols::java_lang_AbstractMethodError(),
- Method::name_and_sig_as_C_string(target_klass(),
- method->name(),
- method->signature()));
- JavaCallArguments args(h_origexception);
- THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
- vmSymbols::throwable_void_signature(),
- &args);
- } else {
- ResourceMark rm(THREAD);
- THROW_MSG_0(vmSymbols::java_lang_AbstractMethodError(),
- Method::name_and_sig_as_C_string(target_klass(),
- method->name(),
- method->signature()));
- }
+ ResourceMark rm(THREAD);
+ Handle h_origexception = Exceptions::new_exception(THREAD,
+ vmSymbols::java_lang_AbstractMethodError(),
+ Method::name_and_sig_as_C_string(target_klass(),
+ method->name(),
+ method->signature()));
+ JavaCallArguments args(h_origexception);
+ THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
+ vmSymbols::throwable_void_signature(),
+ &args);
}
}
}
@@ -1006,7 +980,7 @@
// In the JDK 1.4 reflection implementation, the security check is
// done at the Java level
- if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) {
+ if (!JDK_Version::is_gte_jdk14x_version()) {
// Access checking (unless overridden by Method)
if (!override) {
@@ -1018,7 +992,7 @@
}
}
- } // !(Universe::is_gte_jdk14x_version() && UseNewReflection)
+ } // !Universe::is_gte_jdk14x_version()
assert(ptypes->is_objArray(), "just checking");
int args_len = args.is_null() ? 0 : args->length();
--- a/hotspot/src/share/vm/runtime/reflection.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/reflection.hpp Fri May 23 09:22:01 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -113,11 +113,11 @@
//
// Create a java.lang.reflect.Method object based on a method
- static oop new_method(methodHandle method, bool intern_name, bool for_constant_pool_access, TRAPS);
+ static oop new_method(methodHandle method, bool for_constant_pool_access, TRAPS);
// Create a java.lang.reflect.Constructor object based on a method
static oop new_constructor(methodHandle method, TRAPS);
// Create a java.lang.reflect.Field object based on a field descriptor
- static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS);
+ static oop new_field(fieldDescriptor* fd, TRAPS);
// Create a java.lang.reflect.Parameter object based on a
// MethodParameterElement
static oop new_parameter(Handle method, int index, Symbol* sym,
--- a/hotspot/src/share/vm/runtime/safepoint.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp Fri May 23 09:22:01 2014 -0700
@@ -541,6 +541,13 @@
gclog_or_tty->rotate_log(false);
}
+ {
+ // CMS delays purging the CLDG until the beginning of the next safepoint and to
+ // make sure concurrent sweep is done
+ TraceTime t7("purging class loader data graph", TraceSafepointCleanupTime);
+ ClassLoaderDataGraph::purge_if_needed();
+ }
+
if (MemTracker::is_on()) {
MemTracker::sync();
}
--- a/hotspot/src/share/vm/runtime/vframe.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/runtime/vframe.cpp Fri May 23 09:22:01 2014 -0700
@@ -473,7 +473,7 @@
void vframeStreamCommon::skip_reflection_related_frames() {
while (!at_end() &&
- (JDK_Version::is_gte_jdk14x_version() && UseNewReflection &&
+ (JDK_Version::is_gte_jdk14x_version() &&
(method()->method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) ||
method()->method_holder()->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) {
next();
--- a/hotspot/src/share/vm/trace/traceStream.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/trace/traceStream.hpp Fri May 23 09:22:01 2014 -0700
@@ -66,7 +66,7 @@
}
void print_val(const char* label, s8 val) {
- _st.print("%s = "INT64_FORMAT, label, val);
+ _st.print("%s = "INT64_FORMAT, label, (int64_t) val);
}
void print_val(const char* label, bool val) {
--- a/hotspot/src/share/vm/utilities/accessFlags.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/utilities/accessFlags.hpp Fri May 23 09:22:01 2014 -0700
@@ -54,7 +54,8 @@
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
- JVM_ACC_ON_STACK = 0x00080000, // RedefinedClasses() is used on the stack
+ JVM_ACC_ON_STACK = 0x00080000, // RedefineClasses() was used on the stack
+ JVM_ACC_IS_DELETED = 0x00008000, // RedefineClasses() has deleted this method
// Klass* flags
JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable
@@ -131,6 +132,7 @@
bool has_jsrs () const { return (_flags & JVM_ACC_HAS_JSRS ) != 0; }
bool is_old () const { return (_flags & JVM_ACC_IS_OLD ) != 0; }
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
+ bool is_deleted () const { return (_flags & JVM_ACC_IS_DELETED ) != 0; }
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
// Klass* flags
@@ -195,6 +197,7 @@
void set_has_jsrs() { atomic_set_bits(JVM_ACC_HAS_JSRS); }
void set_is_old() { atomic_set_bits(JVM_ACC_IS_OLD); }
void set_is_obsolete() { atomic_set_bits(JVM_ACC_IS_OBSOLETE); }
+ void set_is_deleted() { atomic_set_bits(JVM_ACC_IS_DELETED); }
void set_is_prefixed_native() { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE); }
void clear_not_c1_compilable() { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE); }
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri May 23 09:22:01 2014 -0700
@@ -1346,6 +1346,9 @@
#ifndef JULONG_FORMAT
#define JULONG_FORMAT UINT64_FORMAT
#endif
+#ifndef JULONG_FORMAT_X
+#define JULONG_FORMAT_X UINT64_FORMAT_X
+#endif
// Format pointers which change size between 32- and 64-bit.
#ifdef _LP64
@@ -1385,7 +1388,7 @@
// All C++ compilers that we know of have the vtbl pointer in the first
// word. If there are exceptions, this function needs to be made compiler
// specific.
-static inline void* dereference_vptr(void* addr) {
+static inline void* dereference_vptr(const void* addr) {
return *(void**)addr;
}
--- a/hotspot/src/share/vm/utilities/workgroup.cpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/utilities/workgroup.cpp Fri May 23 09:22:01 2014 -0700
@@ -378,21 +378,22 @@
WorkGangBarrierSync::WorkGangBarrierSync()
: _monitor(Mutex::safepoint, "work gang barrier sync", true),
- _n_workers(0), _n_completed(0), _should_reset(false) {
+ _n_workers(0), _n_completed(0), _should_reset(false), _aborted(false) {
}
WorkGangBarrierSync::WorkGangBarrierSync(uint n_workers, const char* name)
: _monitor(Mutex::safepoint, name, true),
- _n_workers(n_workers), _n_completed(0), _should_reset(false) {
+ _n_workers(n_workers), _n_completed(0), _should_reset(false), _aborted(false) {
}
void WorkGangBarrierSync::set_n_workers(uint n_workers) {
- _n_workers = n_workers;
- _n_completed = 0;
+ _n_workers = n_workers;
+ _n_completed = 0;
_should_reset = false;
+ _aborted = false;
}
-void WorkGangBarrierSync::enter() {
+bool WorkGangBarrierSync::enter() {
MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
if (should_reset()) {
// The should_reset() was set and we are the first worker to enter
@@ -415,10 +416,17 @@
set_should_reset(true);
monitor()->notify_all();
} else {
- while (n_completed() != n_workers()) {
+ while (n_completed() != n_workers() && !aborted()) {
monitor()->wait(/* no_safepoint_check */ true);
}
}
+ return !aborted();
+}
+
+void WorkGangBarrierSync::abort() {
+ MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
+ set_aborted();
+ monitor()->notify_all();
}
// SubTasksDone functions.
--- a/hotspot/src/share/vm/utilities/workgroup.hpp Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/src/share/vm/utilities/workgroup.hpp Fri May 23 09:22:01 2014 -0700
@@ -359,18 +359,20 @@
class WorkGangBarrierSync : public StackObj {
protected:
Monitor _monitor;
- uint _n_workers;
- uint _n_completed;
+ uint _n_workers;
+ uint _n_completed;
bool _should_reset;
+ bool _aborted;
Monitor* monitor() { return &_monitor; }
uint n_workers() { return _n_workers; }
uint n_completed() { return _n_completed; }
bool should_reset() { return _should_reset; }
+ bool aborted() { return _aborted; }
void zero_completed() { _n_completed = 0; }
void inc_completed() { _n_completed++; }
-
+ void set_aborted() { _aborted = true; }
void set_should_reset(bool v) { _should_reset = v; }
public:
@@ -383,8 +385,14 @@
// Enter the barrier. A worker that enters the barrier will
// not be allowed to leave until all other threads have
- // also entered the barrier.
- void enter();
+ // also entered the barrier or the barrier is aborted.
+ // Returns false if the barrier was aborted.
+ bool enter();
+
+ // Aborts the barrier and wakes up any threads waiting for
+ // the barrier to complete. The barrier will remain in the
+ // aborted state until the next call to set_n_workers().
+ void abort();
};
// A class to manage claiming of subtasks within a group of tasks. The
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/EscapeAnalysis/TestAllocatedEscapesPtrComparison.java Fri May 23 09:22:01 2014 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2014 Google, Inc. All Rights Reserved.
+ * 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 8043354
+ * @summary bcEscapeAnalyzer allocated_escapes not conservative enough
+ * @run main/othervm -XX:CompileOnly=.visitAndPop TestAllocatedEscapesPtrComparison
+ * @author Chuck Rasbold rasbold@google.com
+ */
+
+/*
+ * Test always passes with -XX:-OptmimizePtrCompare
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestAllocatedEscapesPtrComparison {
+
+ static TestAllocatedEscapesPtrComparison dummy;
+
+ class Marker {
+ }
+
+ List<Marker> markerList = new ArrayList<>();
+
+ // Suppress compilation of this method, it must be processed
+ // by the bytecode escape analyzer.
+
+ // Make a new marker and put it on the List
+ Marker getMarker() {
+ // result escapes through markerList
+ final Marker result = new Marker();
+ markerList.add(result);
+ return result;
+ }
+
+ void visit(int depth) {
+ // Make a new marker
+ getMarker();
+
+ // Call visitAndPop every once in a while
+ // Cap the depth of our recursive visits
+ if (depth % 10 == 2) {
+ visitAndPop(depth + 1);
+ } else if (depth < 15) {
+ visit(depth + 1);
+ }
+ }
+
+ void visitAndPop(int depth) {
+ // Random dummy allocation to force EscapeAnalysis to process this method
+ dummy = new TestAllocatedEscapesPtrComparison();
+
+ // Make a new marker
+ Marker marker = getMarker();
+
+ visit(depth + 1);
+
+ // Walk and pop the marker list up to the current marker
+ boolean found = false;
+ for (int i = markerList.size() - 1; i >= 0; i--) {
+ Marker removed = markerList.remove(i);
+
+ // In the failure, EA mistakenly converts this comparison to false
+ if (removed == marker) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ throw new RuntimeException("test fails");
+ }
+ }
+
+
+ public static void main(String args[]) {
+ TestAllocatedEscapesPtrComparison tc = new TestAllocatedEscapesPtrComparison();
+
+ // Warmup and run enough times
+ for (int i = 0; i < 20000; i++) {
+ tc.visit(0);
+ }
+ }
+}
--- a/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java Fri May 23 09:22:01 2014 -0700
@@ -21,6 +21,11 @@
* questions.
*/
+import static com.oracle.java.testlibrary.Asserts.assertEQ;
+import static com.oracle.java.testlibrary.Asserts.assertFalse;
+import static com.oracle.java.testlibrary.Asserts.assertTrue;
+import com.oracle.java.testlibrary.DynamicVMOption;
+
/**
* @test TestDynMaxHeapFreeRatio
* @bug 8028391
@@ -33,32 +38,45 @@
* @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMaxHeapFreeRatio
* @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMaxHeapFreeRatio
*/
-import com.oracle.java.testlibrary.TestDynamicVMOption;
-import com.oracle.java.testlibrary.DynamicVMOptionChecker;
-
-public class TestDynMaxHeapFreeRatio extends TestDynamicVMOption {
-
- public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
- public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
-
- public TestDynMaxHeapFreeRatio() {
- super(MaxFreeRatioFlagName);
- }
-
- public void test() {
-
- int minHeapFreeValue = DynamicVMOptionChecker.getIntValue(MinFreeRatioFlagName);
- System.out.println(MinFreeRatioFlagName + " = " + minHeapFreeValue);
-
- testPercentageValues();
-
- checkInvalidValue(Integer.toString(minHeapFreeValue - 1));
- checkValidValue(Integer.toString(minHeapFreeValue));
- checkValidValue("100");
- }
+public class TestDynMaxHeapFreeRatio {
public static void main(String args[]) throws Exception {
- new TestDynMaxHeapFreeRatio().test();
+
+ // low boundary value
+ int minValue = DynamicVMOption.getInt("MinHeapFreeRatio");
+ System.out.println("MinHeapFreeRatio= " + minValue);
+
+ String badValues[] = {
+ null,
+ "",
+ "not a number",
+ "8.5", "-0.01",
+ Integer.toString(Integer.MIN_VALUE),
+ Integer.toString(Integer.MAX_VALUE),
+ Integer.toString(minValue - 1),
+ "-1024", "-1", "101", "1997"
+ };
+
+ String goodValues[] = {
+ Integer.toString(minValue),
+ Integer.toString(minValue + 1),
+ Integer.toString((minValue + 100) / 2),
+ "99", "100"
+ };
+
+ DynamicVMOption option = new DynamicVMOption("MaxHeapFreeRatio");
+
+ assertTrue(option.isWriteable(), "Option " + option.name
+ + " is expected to be writable");
+
+ for (String v : badValues) {
+ assertFalse(option.isValidValue(v),
+ "'" + v + "' is expected to be illegal for flag " + option.name);
+ }
+ for (String v : goodValues) {
+ option.setValue(v);
+ String newValue = option.getValue();
+ assertEQ(v, newValue);
+ }
}
-
}
--- a/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java Fri May 23 09:22:01 2014 -0700
@@ -33,30 +33,52 @@
* @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMinHeapFreeRatio
* @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMinHeapFreeRatio
*/
-import com.oracle.java.testlibrary.TestDynamicVMOption;
-import com.oracle.java.testlibrary.DynamicVMOptionChecker;
-
-public class TestDynMinHeapFreeRatio extends TestDynamicVMOption {
-
- public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
- public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
+import static com.oracle.java.testlibrary.Asserts.assertEQ;
+import static com.oracle.java.testlibrary.Asserts.assertFalse;
+import static com.oracle.java.testlibrary.Asserts.assertTrue;
+import com.oracle.java.testlibrary.DynamicVMOption;
- public TestDynMinHeapFreeRatio() {
- super(MinFreeRatioFlagName);
- }
-
- public void test() {
- int maxHeapFreeValue = DynamicVMOptionChecker.getIntValue(MaxFreeRatioFlagName);
- System.out.println(MaxFreeRatioFlagName + " = " + maxHeapFreeValue);
-
- testPercentageValues();
-
- checkInvalidValue(Integer.toString(maxHeapFreeValue + 1));
- checkValidValue(Integer.toString(maxHeapFreeValue));
- checkValidValue("0");
- }
+public class TestDynMinHeapFreeRatio {
public static void main(String args[]) throws Exception {
- new TestDynMinHeapFreeRatio().test();
+
+ // high boundary value
+ int maxValue = DynamicVMOption.getInt("MaxHeapFreeRatio");
+ System.out.println("MaxHeapFreeRatio= " + maxValue);
+
+ String badValues[] = {
+ null,
+ "",
+ "not a number",
+ "8.5", "-0.01",
+ Integer.toString(Integer.MIN_VALUE),
+ Integer.toString(Integer.MAX_VALUE),
+ Integer.toString(maxValue + 1),
+ "-1024", "-1", "101", "1997"
+ };
+
+ String goodValues[] = {
+ Integer.toString(maxValue),
+ Integer.toString(maxValue - 1),
+ Integer.toString(maxValue / 2),
+ "0", "1"
+ };
+
+ // option under test
+ DynamicVMOption option = new DynamicVMOption("MinHeapFreeRatio");
+
+ assertTrue(option.isWriteable(), "Option " + option.name
+ + " is expected to be writable");
+
+ for (String v : badValues) {
+ assertFalse(option.isValidValue(v),
+ "'" + v + "' is expected to be illegal for flag " + option.name);
+ }
+
+ for (String v : goodValues) {
+ option.setValue(v);
+ String newValue = option.getValue();
+ assertEQ(v, newValue);
+ }
}
}
--- a/hotspot/test/gc/g1/TestGCLogMessages.java Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java Fri May 23 09:22:01 2014 -0700
@@ -22,7 +22,7 @@
*/
/*
- * @test TestPrintGCDetails
+ * @test TestGCLogMessages
* @bug 8035406 8027295 8035398 8019342
* @summary Ensure that the PrintGCDetails output for a minor GC with G1
* includes the expected necessary messages.
@@ -90,12 +90,6 @@
output.shouldContain("[String Dedup Fixup");
output.shouldContain("[Young Free CSet");
output.shouldContain("[Non-Young Free CSet");
-
- // also check evacuation failure messages once
- output.shouldNotContain("[Evacuation Failure");
- output.shouldNotContain("[Recalculate Used");
- output.shouldNotContain("[Remove Self Forwards");
- output.shouldNotContain("[Restore RemSet");
output.shouldHaveExitValue(0);
}
--- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Fri May 23 09:22:01 2014 -0700
@@ -28,8 +28,7 @@
* @library /testlibrary
* @run main/othervm -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseParallelGC -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 -verbose:gc TestDynShrinkHeap
*/
-
-import com.oracle.java.testlibrary.TestDynamicVMOption;
+import com.oracle.java.testlibrary.DynamicVMOption;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
@@ -44,12 +43,7 @@
private static ArrayList<byte[]> list = new ArrayList<>(0);
private static final int M = 1024 * 1024; // to make heap more manageable by test code
- private final TestDynamicVMOption maxRatioOption;
- private final TestDynamicVMOption minRatioOption;
-
public TestDynShrinkHeap() {
- minRatioOption = new TestDynamicVMOption(MIN_FREE_RATIO_FLAG_NAME);
- maxRatioOption = new TestDynamicVMOption(MAX_FREE_RATIO_FLAG_NAME);
}
private final void test() {
@@ -86,7 +80,8 @@
}
private void free() {
- maxRatioOption.setIntValue(minRatioOption.getIntValue() + 1);
+ int min = DynamicVMOption.getInt(MIN_FREE_RATIO_FLAG_NAME);
+ DynamicVMOption.setInt(MAX_FREE_RATIO_FLAG_NAME, min);
System.gc();
MemoryUsagePrinter.printMemoryUsage("under pressure");
}
--- a/hotspot/test/runtime/7110720/Test7110720.sh Wed May 21 11:25:25 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-#
-# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-
-
-#
-# @test Test7110720.sh
-# @bug 7110720
-# @summary improve VM configuration file loading
-# @run shell Test7110720.sh
-#
-
-if [ "${TESTSRC}" = "" ]
-then
- TESTSRC=${PWD}
- echo "TESTSRC not set. Using "${TESTSRC}" as default"
-fi
-echo "TESTSRC=${TESTSRC}"
-## Adding common setup Variables for running shell tests.
-. ${TESTSRC}/../../test_env.sh
-
-# Jtreg sets TESTVMOPTS which may include -d64 which is
-# required to test a 64-bit JVM on some platforms.
-# If another test harness still creates HOME/JDK64BIT,
-# we can recognise that.
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
- SunOS | Linux | Darwin )
- FS="/"
- RM=/bin/rm
- CP=/bin/cp
- MV=/bin/mv
- ## for solaris, linux it's HOME
- FILE_LOCATION=$HOME
- if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
- then
- TESTVMOPTS=`cat ${FILE_LOCATION}${FS}JDK64BIT`
- fi
- ;;
- Windows_* )
- FS="\\"
- RM=rm
- CP=cp
- MV=mv
- ;;
- CYGWIN_* )
- FS="/"
- RM=rm
- CP=cp
- MV=mv
- ;;
- * )
- echo "Unrecognized system!"
- exit 1;
- ;;
-esac
-
-
-JAVA=${TESTJAVA}${FS}bin${FS}java
-
-# Don't test debug builds, they do read the config files:
-${JAVA} ${TESTVMOPTS} -version 2>&1 | grep "debug" >/dev/null
-if [ "$?" = "0" ]; then
- echo Skipping test for debug build.
- exit 0
-fi
-
-ok=yes
-
-$RM -f .hotspot_compiler .hotspotrc
-
-${JAVA} ${TESTVMOPTS} -version 2>&1 | grep "garbage in" >/dev/null
-if [ "$?" = "0" ]; then
- echo "FAILED: base case failure"
- exit 1
-fi
-
-
-echo "garbage in, garbage out" > .hotspot_compiler
-${JAVA} ${TESTVMOPTS} -version 2>&1 | grep "garbage in" >/dev/null
-if [ "$?" = "0" ]; then
- echo "FAILED: .hotspot_compiler was read"
- ok=no
-fi
-
-$MV .hotspot_compiler hs_comp.txt
-${JAVA} ${TESTVMOPTS} -XX:CompileCommandFile=hs_comp.txt -version 2>&1 | grep "garbage in" >/dev/null
-if [ "$?" = "1" ]; then
- echo "FAILED: explicit compiler command file not read"
- ok=no
-fi
-
-$RM -f .hotspot_compiler hs_comp.txt
-
-echo "garbage" > .hotspotrc
-${JAVA} ${TESTVMOPTS} -version 2>&1 | grep "garbage" >/dev/null
-if [ "$?" = "0" ]; then
- echo "FAILED: .hotspotrc was read"
- ok=no
-fi
-
-$MV .hotspotrc hs_flags.txt
-${JAVA} ${TESTVMOPTS} -XX:Flags=hs_flags.txt -version 2>&1 | grep "garbage" >/dev/null
-if [ "$?" = "1" ]; then
- echo "FAILED: explicit flags file not read"
- ok=no
-fi
-
-if [ "${ok}" = "no" ]; then
- echo "Some tests failed."
- exit 1
-else
- echo "Passed"
- exit 0
-fi
-
--- a/hotspot/test/runtime/CommandLine/CompilerConfigFileWarning.java Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/test/runtime/CommandLine/CompilerConfigFileWarning.java Fri May 23 09:22:01 2014 -0700
@@ -33,17 +33,28 @@
public class CompilerConfigFileWarning {
public static void main(String[] args) throws Exception {
- if (Platform.isDebugBuild()) {
- System.out.println("Skip on debug builds since we'll always read the file there");
- return;
- }
+ ProcessBuilder pb;
+ OutputAnalyzer output;
+ PrintWriter pw;
- PrintWriter pw = new PrintWriter(".hotspot_compiler");
- pw.println("aa");
+ pw = new PrintWriter("hs_comp.txt");
+ pw.println("aaa, aaa");
pw.close();
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-version");
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("warning: .hotspot_compiler file is present but has been ignored. Run with -XX:CompileCommandFile=.hotspot_compiler to load the file.");
+ pb = ProcessTools.createJavaProcessBuilder("-XX:CompileCommandFile=hs_comp.txt", "-version");
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("CompilerOracle: unrecognized line");
+ output.shouldContain("aaa aaa");
+
+ // Skip on debug builds since we'll always read the file there
+ if (!Platform.isDebugBuild()) {
+ pw = new PrintWriter(".hotspot_compiler");
+ pw.println("aa");
+ pw.close();
+
+ pb = ProcessTools.createJavaProcessBuilder("-version");
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("warning: .hotspot_compiler file is present but has been ignored. Run with -XX:CompileCommandFile=.hotspot_compiler to load the file.");
+ }
}
}
--- a/hotspot/test/runtime/CommandLine/ConfigFileWarning.java Wed May 21 11:25:25 2014 +0200
+++ b/hotspot/test/runtime/CommandLine/ConfigFileWarning.java Fri May 23 09:22:01 2014 -0700
@@ -33,17 +33,28 @@
public class ConfigFileWarning {
public static void main(String[] args) throws Exception {
- if (Platform.isDebugBuild()) {
- System.out.println("Skip on debug builds since we'll always read the file there");
- return;
- }
+ PrintWriter pw;
+ ProcessBuilder pb;
+ OutputAnalyzer output;
- PrintWriter pw = new PrintWriter(".hotspotrc");
- pw.println("aa");
+ pw = new PrintWriter("hs_flags.txt");
+ pw.println("aaa");
pw.close();
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-version");
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("warning: .hotspotrc file is present but has been ignored. Run with -XX:Flags=.hotspotrc to load the file.");
+ pb = ProcessTools.createJavaProcessBuilder("-XX:Flags=hs_flags.txt","-version");
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Unrecognized VM option 'aaa'");
+ output.shouldHaveExitValue(1);
+
+ // Skip on debug builds since we'll always read the file there
+ if (!Platform.isDebugBuild()) {
+ pw = new PrintWriter(".hotspotrc");
+ pw.println("aa");
+ pw.close();
+
+ pb = ProcessTools.createJavaProcessBuilder("-version");
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("warning: .hotspotrc file is present but has been ignored. Run with -XX:Flags=.hotspotrc to load the file.");
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/TestHexArguments.java Fri May 23 09:22:01 2014 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 8042885
+ * @summary Make sure there is no error using hexadecimal format in vm options
+ * @author Yumin Qi
+ * @library /testlibrary
+ */
+
+import java.io.File;
+import com.oracle.java.testlibrary.*;
+
+public class TestHexArguments {
+ public static void main(String args[]) throws Exception {
+ String[] javaArgs = {"-XX:SharedBaseAddress=0x1D000000", "-version"};
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, javaArgs);
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("Could not create the Java Virtual Machine");
+ output.shouldHaveExitValue(0);
+
+ String[] javaArgs1 = {"-XX:SharedBaseAddress=1D000000", "-version"};
+ pb = ProcessTools.createJavaProcessBuilder(true, javaArgs1);
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Could not create the Java Virtual Machine");
+ }
+}
--- a/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java Wed May 21 11:25:25 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 CdsWriteError
- * @summary Test how VM handles situation when it is impossible to write the
- * CDS archive. VM is expected to exit gracefully and display the
- * correct reason for the error.
- * @library /testlibrary
- * @run main CdsWriteError
- * @bug 8032222
- */
-
-import com.oracle.java.testlibrary.*;
-import java.io.File;
-
-public class CdsWriteError {
- public static void main(String[] args) throws Exception {
-
- if (Platform.isWindows()) {
- System.out.println("This test is ignored on Windows. This test " +
- "manipulates folder writable attribute, which is known to be " +
- "often ignored by Windows");
-
- return;
- }
-
- // This test has been unstable for Mac OSx (see JDK-8032222)
- if (Platform.isOSX()) {
- System.out.println("This test is skipped on Mac");
- return;
- }
-
- String folderName = "tmp";
- String fileName = folderName + File.separator + "empty.jsa";
-
- // create an empty archive file and make it read only
- File folder = new File(folderName);
- if (!folder.mkdir())
- throw new RuntimeException("Error when creating a tmp folder");
-
- File cdsFile = new File(fileName);
- if (!cdsFile.createNewFile())
- throw new RuntimeException("Error when creating an empty CDS file");
- if (!cdsFile.setWritable(false))
- throw new RuntimeException("Error: could not set writable attribute on cds file");
- if (!folder.setWritable(false))
- throw new RuntimeException("Error: could not set writable attribute on the cds folder");
-
- try {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./" + fileName, "-Xshare:dump");
-
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("Unable to create shared archive file");
- output.shouldHaveExitValue(1);
- } finally {
- // doing this, just in case, to make sure that files can be deleted by the harness
- // on any subsequent run
- folder.setWritable(true);
- cdsFile.setWritable(true);
- }
- }
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/TestEmptyBootstrapMethodsAttr.java Fri May 23 09:22:01 2014 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 TestEmptyBootstrapMethodsAttr
+ * @bug 8041918
+ * @library /testlibrary
+ * @summary Test empty bootstrap_methods table within BootstrapMethods attribute
+ * @compile TestEmptyBootstrapMethodsAttr.java
+ * @run main TestEmptyBootstrapMethodsAttr
+ */
+
+import java.io.File;
+import com.oracle.java.testlibrary.*;
+
+public class TestEmptyBootstrapMethodsAttr {
+
+ public static void main(String args[]) throws Throwable {
+ System.out.println("Regression test for bug 8041918");
+ String jarFile = System.getProperty("test.src") + File.separator + "emptynumbootstrapmethods.jar";
+
+ // ====== extract the test case
+ ProcessBuilder pb = new ProcessBuilder(new String[] { JDKToolFinder.getJDKTool("jar"), "xvf", jarFile } );
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ // Test case #1:
+ // Try loading class with empty bootstrap_methods table where no
+ // other attributes are following BootstrapMethods in attribute table.
+ String className = "emptynumbootstrapmethods1";
+
+ // ======= execute test case #1
+ // Expect a lack of main method, this implies that the class loaded correctly
+ // with an empty bootstrap_methods and did not generate a ClassFormatError.
+ pb = ProcessTools.createJavaProcessBuilder("-cp", ".", className);
+ output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("java.lang.ClassFormatError");
+ output.shouldContain("Main method not found in class " + className);
+ output.shouldHaveExitValue(1);
+
+ // Test case #2:
+ // Try loading class with empty bootstrap_methods table where an
+ // AnnotationDefault attribute follows the BootstrapMethods in the attribute table.
+ className = "emptynumbootstrapmethods2";
+
+ // ======= execute test case #2
+ // Expect a lack of main method, this implies that the class loaded correctly
+ // with an empty bootstrap_methods and did not generate ClassFormatError.
+ pb = ProcessTools.createJavaProcessBuilder("-cp", ".", className);
+ output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("java.lang.ClassFormatError");
+ output.shouldContain("Main method not found in class " + className);
+ output.shouldHaveExitValue(1);
+ }
+}
Binary file hotspot/test/runtime/classFileParserBug/emptynumbootstrapmethods.jar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/emptynumbootstrapmethods1.jcod Fri May 23 09:22:01 2014 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * This test contains a BootstrapMethods attribute with an empty
+ * bootstrap_methods table. This yields a BootstrapMethods
+ * attribute length of 2 and should not cause a
+ * java.lang.ClassFormatError to be thrown.
+ */
+class emptynumbootstrapmethods1 {
+ 0xCAFEBABE;
+ 0; // minor version
+ 51; // version
+ [12] { // Constant Pool
+ ; // first element is empty
+ class #2; // #1 at 0x0A
+ Utf8 "emptynumbootstrapmethods1"; // #2 at 0x0D
+ class #4; // #3 at 0x1F
+ Utf8 "java/lang/Object"; // #4 at 0x22
+ MethodHandle 5b #9; // #5 at 0x35
+ NameAndType #7 #8; // #6 at 0x39
+ Utf8 "equals"; // #7 at 0x3E
+ Utf8 "(Ljava/lang/Object;)Z"; // #8 at 0x47
+ Method #3 #6; // #9 at 0x5F
+ Utf8 "equalsx"; // #10 at 0x3E
+ Utf8 "BootstrapMethods"; // #11 at 0x69
+ } // Constant Pool
+
+ 0x0001; // access
+ #1;// this_cpx
+ #3;// super_cpx
+
+ [0] { // Interfaces
+ } // Interfaces
+
+ [0] { // fields
+ } // fields
+
+ [0] { // methods
+ } // methods
+
+ [1] { // Attributes
+ Attr(#11, 2) { // BootstrapMethods at 0x8A
+ [0] { // bootstrap_methods
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class atrbsm00101m10p
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/classFileParserBug/emptynumbootstrapmethods2.jcod Fri May 23 09:22:01 2014 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * This test contains a BootstrapMethods attribute with an empty
+ * bootstrap_methods table. This yields a BootstrapMethods
+ * attribute length of 2 and should not cause a
+ * java.lang.ClassFormatError to be thrown. To ensure that an empty
+ * bootstrap_methods table is parsed correctly, another attribute,
+ * AnnotationDefault, follows the BootstrapMethods attribute in
+ * the attribute table.
+ */
+
+class emptynumbootstrapmethods2 {
+ 0xCAFEBABE;
+ 0; // minor version
+ 51; // version
+ [14] { // Constant Pool
+ ; // first element is empty
+ class #2; // #1 at 0x0A
+ Utf8 "emptynumbootstrapmethods2"; // #2 at 0x0D
+ class #4; // #3 at 0x1F
+ Utf8 "java/lang/Object"; // #4 at 0x22
+ MethodHandle 5b #9; // #5 at 0x35
+ NameAndType #7 #8; // #6 at 0x39
+ Utf8 "equals"; // #7 at 0x3E
+ Utf8 "(Ljava/lang/Object;)Z"; // #8 at 0x47
+ Method #3 #6; // #9 at 0x5F
+ Utf8 "equalsx"; // #10 at 0x3E
+ Utf8 "BootstrapMethods"; // #11 at 0x69
+ Utf8 "AnnotationDefault"; // #12
+ Utf8 "LAnnotationDefaultI;"; // #13
+ } // Constant Pool
+
+ 0x0001; // access
+ #1;// this_cpx
+ #3;// super_cpx
+
+ [0] { // Interfaces
+ } // Interfaces
+
+ [0] { // fields
+ } // fields
+
+ [0] { // methods
+ } // methods
+
+ [2] { // Attributes
+ Attr(#11, 2) { // BootstrapMethods at 0x8A
+ [0] { // bootstrap_methods
+ }
+ } // end BootstrapMethods
+ ;
+ Attr(#12) { // AnnotationDefault
+ [] { // type annotations
+ { // type annotation
+ 0x00; // target_type
+ 0x00; // type_parameter_index
+ []b { // type_path
+ }
+
+ #13; // type_index
+ [] { // element_value_pairs
+ } // element_value_pairs
+ } // type annotation
+ } // type annotations
+ } // end AnnotationDefault
+ } // Attributes
+} // end class atrbsm00101m10p
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOption.java Fri May 23 09:22:01 2014 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.java.testlibrary;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import java.lang.management.ManagementFactory;
+
+/**
+ * A utility class to work with VM options which could be altered during
+ * execution.
+ *
+ * This class is a wrapper around {@code com.sun.management.VMOption}.
+ * It provides more convenient interface to read/write the values.
+ *
+ */
+public class DynamicVMOption {
+
+ private final HotSpotDiagnosticMXBean mxBean;
+
+ /**
+ * VM option name, like "MinHeapFreeRatio".
+ */
+ public final String name;
+
+ /**
+ * Creates an instance of DynamicVMOption.
+ *
+ * @param name the VM option name
+ */
+ public DynamicVMOption(String name) {
+ this.name = name;
+ mxBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+ }
+
+ /**
+ * Sets a new value for the option.
+ * Trying to set not applicable value will cause IllegalArgumentException.
+ * Behavior with null is undefined, most likely NPE will be thrown.
+ *
+ * @param newValue the value to be set
+ * @see #getValue()
+ * @throws IllegalArgumentException if newValue is not applicable to the option
+ */
+ public final void setValue(String newValue) {
+ mxBean.setVMOption(name, newValue);
+ }
+
+ /**
+ * Returns the value of option.
+ *
+ * @return the current option value
+ * @see #setValue(java.lang.String)
+ */
+ public final String getValue() {
+ return mxBean.getVMOption(name).getValue();
+ }
+
+ /**
+ * Returns true, if option is writable, false otherwise.
+ *
+ * @return true, if option is writable, false otherwise
+ */
+ public final boolean isWriteable() {
+ return mxBean.getVMOption(name).isWriteable();
+ }
+
+ /**
+ * Checks if the given value is applicable for the option.
+ *
+ * This method tries to set the option to the new value. If no exception
+ * has been thrown the value is treated as valid.
+ *
+ * Calling this method will not change the option value. After an attempt
+ * to set a new value, the option will be restored to its previous value.
+ *
+ * @param value the value to verify
+ * @return true if option could be set to the given value
+ */
+ public boolean isValidValue(String value) {
+ boolean isValid = true;
+ String oldValue = getValue();
+ try {
+ setValue(value);
+ } catch (NullPointerException e) {
+ if (value == null) {
+ isValid = false;
+ }
+ } catch (IllegalArgumentException e) {
+ isValid = false;
+ } finally {
+ setValue(oldValue);
+ }
+ return isValid;
+ }
+
+ /**
+ * Returns the value of the given VM option as String.
+ *
+ * This is a simple shortcut for {@code new DynamicVMOption(name).getValue()}
+ *
+ * @param name the name of VM option
+ * @return value as a string
+ * @see #getValue()
+ */
+ public static String getString(String name) {
+ return new DynamicVMOption(name).getValue();
+ }
+
+ /**
+ * Returns the value of the given option as int.
+ *
+ * @param name the name of VM option
+ * @return value parsed as integer
+ * @see #getString(java.lang.String)
+ *
+ */
+ public static int getInt(String name) {
+ return Integer.parseInt(getString(name));
+ }
+
+ /**
+ * Sets the VM option to a new value.
+ *
+ * This is a simple shortcut for {@code new DynamicVMOption(name).setValue(value)}
+ *
+ * @param name the name of VM option
+ * @param value the value to be set
+ * @see #setValue(java.lang.String)
+ */
+ public static void setString(String name, String value) {
+ new DynamicVMOption(name).setValue(value);
+ }
+
+ /**
+ * Sets the VM option value to a new integer value.
+ *
+ * @param name the name of VM option
+ * @param value the integer value to be set
+ * @see #setString(java.lang.String, java.lang.String)
+ */
+ public static void setInt(String name, int value) {
+ new DynamicVMOption(name).setValue(Integer.toString(value));
+ }
+
+}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOptionChecker.java Wed May 21 11:25:25 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.java.testlibrary;
-
-import com.sun.management.HotSpotDiagnosticMXBean;
-import com.sun.management.VMOption;
-import java.lang.management.ManagementFactory;
-
-/**
- * Simple class to check writeability, invalid and valid values for VMOption
- */
-public class DynamicVMOptionChecker {
-
- /**
- * Reads VM option from PlatformMXBean and parse it to integer value
- *
- * @param name of option
- * @return parsed value
- */
- public static int getIntValue(String name) {
-
- VMOption option = ManagementFactory.
- getPlatformMXBean(HotSpotDiagnosticMXBean.class).
- getVMOption(name);
-
- return Integer.parseInt(option.getValue());
- }
-
- /**
- * Sets VM option value
- *
- * @param name of option
- * @param value to set
- */
- public static void setIntValue(String name, int value) {
- ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class).setVMOption(name, Integer.toString(value));
- }
-
- /**
- * Checks that VM option is dynamically writable
- *
- * @param name
- * @throws RuntimeException if option if not writable
- * @return always true
- */
- public static boolean checkIsWritable(String name) {
- VMOption option = ManagementFactory.
- getPlatformMXBean(HotSpotDiagnosticMXBean.class).
- getVMOption(name);
-
- if (!option.isWriteable()) {
- throw new RuntimeException(name + " is not writable");
- }
-
- return true;
- }
-
- /**
- * Checks that value cannot be set
- *
- * @param name of flag
- * @param value string representation of value to set
- * @throws RuntimeException on error - when expected exception hasn't been thrown
- */
- public static void checkInvalidValue(String name, String value) {
- // should throw
- try {
- ManagementFactory.
- getPlatformMXBean(HotSpotDiagnosticMXBean.class).
- setVMOption(name, value);
-
- } catch (IllegalArgumentException e) {
- return;
- }
-
- throw new RuntimeException("Expected IllegalArgumentException was not thrown, " + name + "= " + value);
- }
-
- /**
- * Checks that value can be set
- *
- * @param name of flag to set
- * @param value string representation of value to set
- * @throws RuntimeException on error - when value in VM is not equal to origin
- */
- public static void checkValidValue(String name, String value) {
- ManagementFactory.
- getPlatformMXBean(HotSpotDiagnosticMXBean.class).
- setVMOption(name, value);
-
- VMOption option = ManagementFactory.
- getPlatformMXBean(HotSpotDiagnosticMXBean.class).
- getVMOption(name);
-
- if (!option.getValue().equals(value)) {
- throw new RuntimeException("Actual value of " + name + " \"" + option.getValue()
- + "\" not equal origin \"" + value + "\"");
- }
- }
-
-}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/TestDynamicVMOption.java Wed May 21 11:25:25 2014 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.java.testlibrary;
-
-/**
- * Simple class to check writeability, invalid and valid values for concrete VMOption
- */
-public class TestDynamicVMOption {
-
- private final String name;
- private final int value;
-
- /**
- * Constructor
- *
- * @param name of VM option to test
- */
- public TestDynamicVMOption(String name) {
- this.name = name;
- this.value = DynamicVMOptionChecker.getIntValue(name);
- System.out.println(this.name + " = " + this.value);
- }
-
- /**
- * Checks that this value can accept valid percentage values and cannot accept invalid percentage values
- *
- * @throws RuntimeException
- */
- public void testPercentageValues() {
- checkInvalidValue(Integer.toString(Integer.MIN_VALUE));
- checkInvalidValue(Integer.toString(Integer.MAX_VALUE));
- checkInvalidValue("-10");
- checkInvalidValue("190");
- }
-
- /**
- * Reads VM option from PlatformMXBean and parse it to integer value
- *
- * @return value
- */
- public int getIntValue() {
- return DynamicVMOptionChecker.getIntValue(this.name);
- }
-
- /**
- * Sets VM option value
- *
- * @param value to set
- */
- public void setIntValue(int value) {
- DynamicVMOptionChecker.setIntValue(this.name, value);
- }
-
- /**
- * Checks that this VM option is dynamically writable
- *
- * @throws RuntimeException if option if not writable
- * @return true
- */
- public boolean checkIsWritable() throws RuntimeException {
- return DynamicVMOptionChecker.checkIsWritable(this.name);
- }
-
- /**
- * Checks that value for this VM option cannot be set
- *
- * @param value to check
- * @throws RuntimeException on error - when expected exception hasn't been thrown
- */
- public void checkInvalidValue(String value) {
- DynamicVMOptionChecker.checkInvalidValue(this.name, value);
- }
-
- /**
- * Checks that value for this VM option can be set
- *
- * @param value to check
- * @throws RuntimeException on error - when value in VM is not equal to origin
- */
- public void checkValidValue(String value) {
- DynamicVMOptionChecker.checkValidValue(this.name, value);
- }
-
-}