Mercurial > hg > truffle
changeset 1966:4110c3e0c50d
Merge
author | iveresov |
---|---|
date | Fri, 19 Nov 2010 17:01:34 -0800 |
parents | 0be53e62c06c (diff) f264f4c42799 (current diff) |
children | a6b067997c7e b675ff1ca7a3 |
files | src/share/vm/memory/universe.cpp src/share/vm/runtime/arguments.cpp |
diffstat | 16 files changed, 242 insertions(+), 103 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Nov 18 09:52:48 2010 -0800 +++ b/.hgtags Fri Nov 19 17:01:34 2010 -0800 @@ -128,3 +128,6 @@ bdbc48857210a509b3c50a3291ecb9dd6a72e016 jdk7-b115 96b3f2a7add0b445b8aa421f6823cff5a2e2fe03 jdk7-b116 52f19c724d9634af79044a2e0defbe4a5f1adbda hs20-b02 +806d0c037e6bbb88dac0699673f4ba55ee8c02da jdk7-b117 +698b7b727e12de44139d8cca6ab9a494ead13253 jdk7-b118 +3ef7426b4deac5dcfd4afb35cabe9ab3d666df91 hs20-b02
--- a/make/hotspot_version Thu Nov 18 09:52:48 2010 -0800 +++ b/make/hotspot_version Fri Nov 19 17:01:34 2010 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=20 HS_MINOR_VER=0 -HS_BUILD_NUMBER=02 +HS_BUILD_NUMBER=03 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/src/share/vm/classfile/verifier.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/classfile/verifier.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -247,6 +247,10 @@ ClassVerifier::~ClassVerifier() { } +VerificationType ClassVerifier::object_type() const { + return VerificationType::reference_type(vmSymbols::java_lang_Object()); +} + void ClassVerifier::verify_class(TRAPS) { if (_verify_verbose) { tty->print_cr("Verifying class %s with new format", @@ -726,8 +730,7 @@ } no_control_flow = false; break; case Bytecodes::_aastore : - type = current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + type = current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); type2 = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); atype = current_frame.pop_stack( @@ -1232,8 +1235,7 @@ { index = bcs.get_index_u2(); verify_cp_class_type(index, cp, CHECK_VERIFY(this)); - current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); VerificationType klass_type = cp_index_to_type( index, cp, CHECK_VERIFY(this)); current_frame.push_stack(klass_type, CHECK_VERIFY(this)); @@ -1242,8 +1244,7 @@ case Bytecodes::_instanceof : { index = bcs.get_index_u2(); verify_cp_class_type(index, cp, CHECK_VERIFY(this)); - current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); no_control_flow = false; break; @@ -1610,9 +1611,7 @@ verify_cp_type(index, cp, types, CHECK_VERIFY(this)); } if (tag.is_string() && cp->is_pseudo_string_at(index)) { - current_frame->push_stack( - VerificationType::reference_type( - vmSymbols::java_lang_Object()), CHECK_VERIFY(this)); + current_frame->push_stack(object_type(), CHECK_VERIFY(this)); } else if (tag.is_string() || tag.is_unresolved_string()) { current_frame->push_stack( VerificationType::reference_type(
--- a/src/share/vm/classfile/verifier.hpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/classfile/verifier.hpp Fri Nov 19 17:01:34 2010 -0800 @@ -157,6 +157,8 @@ bool name_in_supers(symbolOop ref_name, instanceKlassHandle current); + VerificationType object_type() const; + instanceKlassHandle _klass; // the class being verified methodHandle _method; // current method being verified VerificationType _this_type; // the verification type of the current class
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -1093,7 +1093,9 @@ // perm_gen_verify_bit_map where we store the "deadness" information if // we did not sweep the perm gen in the most recent previous GC cycle. bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const { - assert (block_is_obj(p), "The address should point to an object"); + assert(SafepointSynchronize::is_at_safepoint() || !is_init_completed(), + "Else races are possible"); + assert(block_is_obj(p), "The address should point to an object"); // If we're sweeping, we use object liveness information from the main bit map // for both perm gen and old gen. @@ -1102,9 +1104,14 @@ // main marking bit map (live_map below) is locked, // OR we're in other phases and perm_gen_verify_bit_map (dead_map below) // is stable, because it's mutated only in the sweeping phase. + // NOTE: This method is also used by jmap where, if class unloading is + // off, the results can return "false" for legitimate perm objects, + // when we are not in the midst of a sweeping phase, which can result + // in jmap not reporting certain perm gen objects. This will be moot + // if/when the perm gen goes away in the future. if (_collector->abstract_state() == CMSCollector::Sweeping) { CMSBitMap* live_map = _collector->markBitMap(); - return live_map->isMarked((HeapWord*) p); + return live_map->par_isMarked((HeapWord*) p); } else { // If we're not currently sweeping and we haven't swept the perm gen in // the previous concurrent cycle then we may have dead but unswept objects @@ -2266,7 +2273,7 @@ } void CompactibleFreeListSpace::print() const { - Space::print_on(tty); + print_on(tty); } void CompactibleFreeListSpace::prepare_for_verify() {
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -795,6 +795,7 @@ _worker_i(worker_i), _g1h(g1) { } + bool doHeapRegion(HeapRegion* r) { if (!r->continuesHumongous()) { _cl.set_from(r);
--- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -116,7 +116,6 @@ : _g1(g1), _conc_refine_cards(0), _ct_bs(ct_bs), _g1p(_g1->g1_policy()), _cg1r(g1->concurrent_g1_refine()), - _traversal_in_progress(false), _cset_rs_update_cl(NULL), _cards_scanned(NULL), _total_cards_scanned(0) { @@ -512,8 +511,6 @@ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); dcqs.concatenate_logs(); - assert(!_traversal_in_progress, "Invariant between iterations."); - set_traversal(true); if (ParallelGCThreads > 0) { _seq_task->set_n_threads((int)n_workers()); } @@ -539,9 +536,6 @@ // through the oops which coincide with that card. It scans the reference // fields in each oop; when it finds an oop that points into the collection // set, the RSet for the region containing the referenced object is updated. -// Note: _par_traversal_in_progress in the G1RemSet must be FALSE; otherwise -// the UpdateRSetImmediate closure will cause cards to be enqueued on to -// the DCQS that we're iterating over, causing an infinite loop. class UpdateRSetCardTableEntryIntoCSetClosure: public CardTableEntryClosure { G1CollectedHeap* _g1; CardTableModRefBS* _ct_bs; @@ -611,8 +605,6 @@ // Set all cards back to clean. _g1->cleanUpCardTable(); - set_traversal(false); - DirtyCardQueueSet& into_cset_dcqs = _g1->into_cset_dirty_card_queue_set(); int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num(); @@ -645,21 +637,8 @@ assert(_g1->into_cset_dirty_card_queue_set().completed_buffers_num() == 0, "all buffers should be freed"); _g1->into_cset_dirty_card_queue_set().clear_n_completed_buffers(); - - assert(!_traversal_in_progress, "Invariant between iterations."); } -class UpdateRSObjectClosure: public ObjectClosure { - UpdateRSOopClosure* _update_rs_oop_cl; -public: - UpdateRSObjectClosure(UpdateRSOopClosure* update_rs_oop_cl) : - _update_rs_oop_cl(update_rs_oop_cl) {} - void do_object(oop obj) { - obj->oop_iterate(_update_rs_oop_cl); - } - -}; - class ScrubRSClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; BitMap* _region_bm; @@ -749,7 +728,12 @@ ct_freq_note_card(_ct_bs->index_for(start)); #endif - UpdateRSOopClosure update_rs_oop_cl(this, worker_i); + assert(!check_for_refs_into_cset || _cset_rs_update_cl[worker_i] != NULL, "sanity"); + UpdateRSOrPushRefOopClosure update_rs_oop_cl(_g1, + _g1->g1_rem_set(), + _cset_rs_update_cl[worker_i], + check_for_refs_into_cset, + worker_i); update_rs_oop_cl.set_from(r); TriggerClosure trigger_cl;
--- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp Fri Nov 19 17:01:34 2010 -0800 @@ -59,11 +59,6 @@ size_t* _cards_scanned; size_t _total_cards_scanned; - // _traversal_in_progress is "true" iff a traversal is in progress. - - bool _traversal_in_progress; - void set_traversal(bool b) { _traversal_in_progress = b; } - // Used for caching the closure that is responsible for scanning // references into the collection set. OopsInHeapRegionClosure** _cset_rs_update_cl; @@ -76,10 +71,6 @@ bool concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, bool check_for_refs_into_cset); -protected: - template <class T> void write_ref_nv(HeapRegion* from, T* p); - template <class T> void par_write_ref_nv(HeapRegion* from, T* p, int tid); - public: // This is called to reset dual hash tables after the gc pause // is finished and the initial hash table is no longer being @@ -117,22 +108,8 @@ // Record, if necessary, the fact that *p (where "p" is in region "from", // which is required to be non-NULL) has changed to a new non-NULL value. - // [Below the virtual version calls a non-virtual protected - // workhorse that is templatified for narrow vs wide oop.] - inline void write_ref(HeapRegion* from, oop* p) { - write_ref_nv(from, p); - } - inline void write_ref(HeapRegion* from, narrowOop* p) { - write_ref_nv(from, p); - } - inline void par_write_ref(HeapRegion* from, oop* p, int tid) { - par_write_ref_nv(from, p, tid); - } - inline void par_write_ref(HeapRegion* from, narrowOop* p, int tid) { - par_write_ref_nv(from, p, tid); - } - - bool self_forwarded(oop obj); + template <class T> void write_ref(HeapRegion* from, T* p); + template <class T> void par_write_ref(HeapRegion* from, T* p, int tid); // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region // or card, respectively, such that a region or card with a corresponding @@ -186,9 +163,8 @@ public: UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) : - _from(NULL), _rs(rs), _worker_i(worker_i) { - guarantee(_rs != NULL, "Requires an HRIntoG1RemSet"); - } + _from(NULL), _rs(rs), _worker_i(worker_i) + {} void set_from(HeapRegion* from) { assert(from != NULL, "from region must be non-NULL"); @@ -215,3 +191,43 @@ virtual void do_oop(narrowOop* p) { do_oop_work(p); } virtual void do_oop( oop* p) { do_oop_work(p); } }; + +class UpdateRSOrPushRefOopClosure: public OopClosure { + G1CollectedHeap* _g1; + G1RemSet* _g1_rem_set; + HeapRegion* _from; + OopsInHeapRegionClosure* _push_ref_cl; + bool _record_refs_into_cset; + int _worker_i; + + template <class T> void do_oop_work(T* p); + +public: + UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, + G1RemSet* rs, + OopsInHeapRegionClosure* push_ref_cl, + bool record_refs_into_cset, + int worker_i = 0) : + _g1(g1h), + _g1_rem_set(rs), + _from(NULL), + _record_refs_into_cset(record_refs_into_cset), + _push_ref_cl(push_ref_cl), + _worker_i(worker_i) { } + + void set_from(HeapRegion* from) { + assert(from != NULL, "from region must be non-NULL"); + _from = from; + } + + bool self_forwarded(oop obj) { + bool result = (obj->is_forwarded() && (obj->forwardee()== obj)); + return result; + } + + virtual void do_oop(narrowOop* p) { do_oop_work(p); } + virtual void do_oop(oop* p) { do_oop_work(p); } + + bool apply_to_weak_ref_discovered_field() { return true; } +}; +
--- a/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp Fri Nov 19 17:01:34 2010 -0800 @@ -31,17 +31,12 @@ } template <class T> -inline void G1RemSet::write_ref_nv(HeapRegion* from, T* p) { - par_write_ref_nv(from, p, 0); -} - -inline bool G1RemSet::self_forwarded(oop obj) { - bool result = (obj->is_forwarded() && (obj->forwardee()== obj)); - return result; +inline void G1RemSet::write_ref(HeapRegion* from, T* p) { + par_write_ref(from, p, 0); } template <class T> -inline void G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) { +inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) { oop obj = oopDesc::load_decode_heap_oop(p); #ifdef ASSERT // can't do because of races @@ -62,34 +57,15 @@ assert(from == NULL || from->is_in_reserved(p), "p is not in from"); HeapRegion* to = _g1->heap_region_containing(obj); - // The test below could be optimized by applying a bit op to to and from. - if (to != NULL && from != NULL && from != to) { - // The _traversal_in_progress flag is true during the collection pause, - // false during the evacuation failure handling. This should avoid a - // potential loop if we were to add the card containing 'p' to the DCQS - // that's used to regenerate the remembered sets for the collection set, - // in the event of an evacuation failure, here. The UpdateRSImmediate - // closure will eventally call this routine. - if (_traversal_in_progress && - to->in_collection_set() && !self_forwarded(obj)) { - - assert(_cset_rs_update_cl[tid] != NULL, "should have been set already"); - _cset_rs_update_cl[tid]->do_oop(p); - - // Deferred updates to the CSet are either discarded (in the normal case), - // or processed (if an evacuation failure occurs) at the end - // of the collection. - // See G1RemSet::cleanup_after_oops_into_collection_set_do(). - } else { + if (to != NULL && from != to) { #if G1_REM_SET_LOGGING - gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS" - " for region [" PTR_FORMAT ", " PTR_FORMAT ")", - p, obj, - to->bottom(), to->end()); + gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS" + " for region [" PTR_FORMAT ", " PTR_FORMAT ")", + p, obj, + to->bottom(), to->end()); #endif - assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); - to->rem_set()->add_reference(p, tid); - } + assert(to->rem_set() != NULL, "Need per-region 'into' remsets."); + to->rem_set()->add_reference(p, tid); } } @@ -108,3 +84,64 @@ } } +template <class T> +inline void UpdateRSOrPushRefOopClosure::do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop(p); +#ifdef ASSERT + // can't do because of races + // assert(obj == NULL || obj->is_oop(), "expected an oop"); + + // Do the safe subset of is_oop + if (obj != NULL) { +#ifdef CHECK_UNHANDLED_OOPS + oopDesc* o = obj.obj(); +#else + oopDesc* o = obj; +#endif // CHECK_UNHANDLED_OOPS + assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned"); + assert(Universe::heap()->is_in_reserved(obj), "must be in heap"); + } +#endif // ASSERT + + assert(_from != NULL, "from region must be non-NULL"); + + HeapRegion* to = _g1->heap_region_containing(obj); + if (to != NULL && _from != to) { + // The _record_refs_into_cset flag is true during the RSet + // updating part of an evacuation pause. It is false at all + // other times: + // * rebuilding the rembered sets after a full GC + // * during concurrent refinement. + // * updating the remembered sets of regions in the collection + // set in the event of an evacuation failure (when deferred + // updates are enabled). + + if (_record_refs_into_cset && to->in_collection_set()) { + // We are recording references that point into the collection + // set and this particular reference does exactly that... + // If the referenced object has already been forwarded + // to itself, we are handling an evacuation failure and + // we have already visited/tried to copy this object + // there is no need to retry. + if (!self_forwarded(obj)) { + assert(_push_ref_cl != NULL, "should not be null"); + // Push the reference in the refs queue of the G1ParScanThreadState + // instance for this worker thread. + _push_ref_cl->do_oop(p); + } + + // Deferred updates to the CSet are either discarded (in the normal case), + // or processed (if an evacuation failure occurs) at the end + // of the collection. + // See G1RemSet::cleanup_after_oops_into_collection_set_do(). + } else { + // We either don't care about pushing references that point into the + // collection set (i.e. we're not during an evacuation pause) _or_ + // the reference doesn't point into the collection set. Either way + // we add the reference directly to the RSet of the region containing + // the referenced object. + _g1_rem_set->par_write_ref(_from, p, _worker_i); + } + } +} +
--- a/src/share/vm/includeDB_core Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/includeDB_core Fri Nov 19 17:01:34 2010 -0800 @@ -4454,6 +4454,7 @@ universe.cpp generation.hpp universe.cpp handles.inline.hpp universe.cpp hashtable.inline.hpp +universe.cpp init.hpp universe.cpp instanceKlass.hpp universe.cpp instanceKlassKlass.hpp universe.cpp instanceRefKlass.hpp
--- a/src/share/vm/memory/defNewGeneration.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/memory/defNewGeneration.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -838,7 +838,9 @@ gch->incremental_collection_failed()) { seen_incremental_collection_failed = true; } else if (seen_incremental_collection_failed) { - assert(!gch->incremental_collection_failed(), "Twice in a row"); + assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed(), + "Twice in a row"); + seen_incremental_collection_failed = false; } #endif // ASSERT
--- a/src/share/vm/memory/universe.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/memory/universe.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -946,6 +946,7 @@ extern void initialize_converter_functions(); bool universe_post_init() { + assert(!is_init_completed(), "Error: initialization not yet completed!"); Universe::_fully_initialized = true; EXCEPTION_MARK; { ResourceMark rm;
--- a/src/share/vm/runtime/arguments.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/runtime/arguments.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -116,7 +116,6 @@ // Initialize system properties key and value. void Arguments::init_system_properties() { - PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.version", "1.0", false)); PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name", "Java Virtual Machine Specification", false)); PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(), false)); @@ -151,9 +150,23 @@ // Update/Initialize System properties after JDK version number is known void Arguments::init_version_specific_system_properties() { - PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.vendor", - JDK_Version::is_gte_jdk17x_version() ? "Oracle Corporation" : "Sun Microsystems Inc.", false)); - PropertyList_add(&_system_properties, new SystemProperty("java.vm.vendor", VM_Version::vm_vendor(), false)); + enum { bufsz = 16 }; + char buffer[bufsz]; + const char* spec_vendor = "Sun Microsystems Inc."; + uint32_t spec_version = 0; + + if (JDK_Version::is_gte_jdk17x_version()) { + spec_vendor = "Oracle Corporation"; + spec_version = JDK_Version::current().major_version(); + } + jio_snprintf(buffer, bufsz, "1." UINT32_FORMAT, spec_version); + + PropertyList_add(&_system_properties, + new SystemProperty("java.vm.specification.vendor", spec_vendor, false)); + PropertyList_add(&_system_properties, + new SystemProperty("java.vm.specification.version", buffer, false)); + PropertyList_add(&_system_properties, + new SystemProperty("java.vm.vendor", VM_Version::vm_vendor(), false)); } /**
--- a/src/share/vm/runtime/init.cpp Thu Nov 18 09:52:48 2010 -0800 +++ b/src/share/vm/runtime/init.cpp Fri Nov 19 17:01:34 2010 -0800 @@ -160,5 +160,6 @@ void set_init_completed() { + assert(Universe::is_fully_initialized(), "Should have completed initialization"); _init_completed = true; }
--- a/test/compiler/6857159/Test6857159.java Thu Nov 18 09:52:48 2010 -0800 +++ b/test/compiler/6857159/Test6857159.java Fri Nov 19 17:01:34 2010 -0800 @@ -54,7 +54,7 @@ } public static void main(String[] args) throws Exception { - for (int i = 0; i < 100000; i++) { + for (int i = 0; i < 20000; i++) { Thread t = null; switch (i % 3) { case 0: t = new ct0(); break;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/6981737/Test6981737.java Fri Nov 19 17:01:34 2010 -0800 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test Test6981737.java + * @bug 6981737 + * @summary check for correct vm properties + * @run main Test6981737 + * @author kamg +*/ + +public class Test6981737 { + + /** + * Check the 'vendor' properties java.vm.specification.version + * property. Before jdk7, they should be "Sun Micro..." and "1.0". + * In jdk7 onwards they should be "Oracle..." and "1.<major_version>" + */ + public static void main(String[] args) throws Exception { + + String version = verifyProperty("java.version", "[0-9]+\\.[0-9]+\\..*"); + String major_version_spec = version.split("\\.")[1]; + int major_version = new Integer(major_version_spec).intValue(); + + String vendor_re = "Oracle Corporation"; + String vm_spec_version_re = "1\\." + major_version_spec; + if (major_version < 7) { + vendor_re = "Sun Microsystems Inc\\."; + vm_spec_version_re = "1\\.0"; + } + verifyProperty("java.vendor", vendor_re); + verifyProperty("java.vm.vendor", vendor_re); + verifyProperty("java.vm.specification.vendor", vendor_re); + verifyProperty("java.specification.vendor", vendor_re); + verifyProperty("java.vm.specification.version", vm_spec_version_re); + System.out.println("PASS"); + } + + public static String verifyProperty(String name, String expected_re) { + String value = System.getProperty(name, ""); + System.out.print("Checking " + name + ": \"" + value + + "\".matches(\"" + expected_re + "\")... "); + if (!value.matches(expected_re)) { + System.out.println("no."); + throw new RuntimeException("FAIL: Wrong value for " + name + + " property, \"" + value + "\", expected to be of form: \"" + + expected_re + "\""); + } + System.out.println("yes."); + return value; + } +}