Merge
authorjiangli
Mon, 23 Nov 2015 14:38:20 -0500
changeset 34259 06047e5d60d2
parent 34258 fb4f53f3e92f (current diff)
parent 34252 59d76c40998a (diff)
child 34260 140ad0a387ff
child 34265 fdd66cad641d
Merge
hotspot/src/share/vm/memory/metaspaceShared.hpp
--- a/hotspot/make/test/JtregNative.gmk	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/make/test/JtregNative.gmk	Mon Nov 23 14:38:20 2015 -0500
@@ -51,7 +51,8 @@
 # Add conditional directories here when needed.
 ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
 BUILD_HOTSPOT_JTREG_NATIVE_SRC += \
-    $(HOTSPOT_TOPDIR)/test/runtime/libadimalloc.solaris.sparc
+    $(HOTSPOT_TOPDIR)/test/runtime/libadimalloc.solaris.sparc \
+    $(HOTSPOT_TOPDIR)/test/runtime/ThreadSignalMask
 endif
 
 ifeq ($(TOOLCHAIN_TYPE), solstudio)
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -137,7 +137,7 @@
   if (_type == CompactHashtable<Symbol*, char>::_symbol_table) {
     base_address = uintx(MetaspaceShared::shared_rs()->base());
     max_delta    = uintx(MetaspaceShared::shared_rs()->size());
-    assert(max_delta <= 0x7fffffff, "range check");
+    assert(max_delta <= MAX_SHARED_DELTA, "range check");
   } else {
     assert((_type == CompactHashtable<oop, char>::_string_table), "unknown table");
     assert(UseCompressedOops, "UseCompressedOops is required");
--- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -499,11 +499,14 @@
   return _next_offset_threshold;
 }
 
-void G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* obj_top) {
+void G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* obj_top, size_t fill_size) {
   // The first BOT entry should have offset 0.
   reset_bot();
   alloc_block(_bottom, obj_top);
- }
+  if (fill_size > 0) {
+    alloc_block(obj_top, fill_size);
+  }
+}
 
 #ifndef PRODUCT
 void G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
--- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -372,7 +372,7 @@
   HeapWord* block_start_unsafe(const void* addr);
   HeapWord* block_start_unsafe_const(const void* addr) const;
 
-  void set_for_starts_humongous(HeapWord* obj_top);
+  void set_for_starts_humongous(HeapWord* obj_top, size_t fill_size);
 
   virtual void print_on(outputStream* out) PRODUCT_RETURN;
 };
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -339,11 +339,18 @@
   // thread to calculate the object size incorrectly.
   Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
 
+  size_t fill_size = word_size_sum - word_size;
+  if (fill_size >= min_fill_size()) {
+    fill_with_objects(obj_top, fill_size);
+  } else {
+    fill_size = 0;
+  }
+
   // We will set up the first region as "starts humongous". This
   // will also update the BOT covering all the regions to reflect
   // that there is a single object that starts at the bottom of the
   // first region.
-  first_hr->set_starts_humongous(obj_top);
+  first_hr->set_starts_humongous(obj_top, fill_size);
   first_hr->set_allocation_context(context);
   // Then, if there are any, we will set up the "continues
   // humongous" regions.
@@ -365,9 +372,9 @@
 
   // Now that the BOT and the object header have been initialized,
   // we can update top of the "starts humongous" region.
-  first_hr->set_top(MIN2(first_hr->end(), obj_top));
+  first_hr->set_top(first_hr->end());
   if (_hr_printer.is_active()) {
-    _hr_printer.alloc(G1HRPrinter::StartsHumongous, first_hr, first_hr->top());
+    _hr_printer.alloc(G1HRPrinter::StartsHumongous, first_hr, first_hr->end());
   }
 
   // Now, we will update the top fields of the "continues humongous"
@@ -375,25 +382,18 @@
   hr = NULL;
   for (uint i = first + 1; i < last; ++i) {
     hr = region_at(i);
-    if ((i + 1) == last) {
-      // last continues humongous region
-      assert(hr->bottom() < obj_top && obj_top <= hr->end(),
-             "new_top should fall on this region");
-      hr->set_top(obj_top);
-      _hr_printer.alloc(G1HRPrinter::ContinuesHumongous, hr, obj_top);
-    } else {
-      // not last one
-      assert(obj_top > hr->end(), "obj_top should be above this region");
-      hr->set_top(hr->end());
+    hr->set_top(hr->end());
+    if (_hr_printer.is_active()) {
       _hr_printer.alloc(G1HRPrinter::ContinuesHumongous, hr, hr->end());
     }
   }
-  // If we have continues humongous regions (hr != NULL), its top should
-  // match obj_top.
-  assert(hr == NULL || (hr->top() == obj_top), "sanity");
+
+  assert(hr == NULL || (hr->bottom() < obj_top && obj_top <= hr->end()),
+         "obj_top should be in last region");
+
   check_bitmaps("Humongous Region Allocation", first_hr);
 
-  increase_used(word_size * HeapWordSize);
+  increase_used(word_size_sum * HeapWordSize);
 
   for (uint i = first; i < last; ++i) {
     _humongous_set.add(region_at(i));
@@ -1202,9 +1202,8 @@
   heap_region_iterate(&cl);
 }
 
-bool G1CollectedHeap::do_collection(bool explicit_gc,
-                                    bool clear_all_soft_refs,
-                                    size_t word_size) {
+bool G1CollectedHeap::do_full_collection(bool explicit_gc,
+                                         bool clear_all_soft_refs) {
   assert_at_safepoint(true /* should_be_vm_thread */);
 
   if (GC_locker::check_active_before_gc()) {
@@ -1362,8 +1361,7 @@
       clear_rsets_post_compaction();
       check_gc_time_stamps();
 
-      // Resize the heap if necessary.
-      resize_if_necessary_after_full_collection(explicit_gc ? 0 : word_size);
+      resize_if_necessary_after_full_collection();
 
       if (_hr_printer.is_active()) {
         // We should do this after we potentially resize the heap so
@@ -1471,22 +1469,15 @@
 }
 
 void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
-  // do_collection() will return whether it succeeded in performing
-  // the GC. Currently, there is no facility on the
-  // do_full_collection() API to notify the caller than the collection
-  // did not succeed (e.g., because it was locked out by the GC
-  // locker). So, right now, we'll ignore the return value.
-  bool dummy = do_collection(true,                /* explicit_gc */
-                             clear_all_soft_refs,
-                             0                    /* word_size */);
-}
-
-// This code is mostly copied from TenuredGeneration.
-void
-G1CollectedHeap::
-resize_if_necessary_after_full_collection(size_t word_size) {
-  // Include the current allocation, if any, and bytes that will be
-  // pre-allocated to support collections, as "used".
+  // Currently, there is no facility in the do_full_collection(bool) API to notify
+  // the caller that the collection did not succeed (e.g., because it was locked
+  // out by the GC locker). So, right now, we'll ignore the return value.
+  bool dummy = do_full_collection(true,                /* explicit_gc */
+                                  clear_all_soft_refs);
+}
+
+void G1CollectedHeap::resize_if_necessary_after_full_collection() {
+  // Include bytes that will be pre-allocated to support collections, as "used".
   const size_t used_after_gc = used();
   const size_t capacity_after_gc = capacity();
   const size_t free_after_gc = capacity_after_gc - used_after_gc;
@@ -1598,9 +1589,8 @@
 
   if (do_gc) {
     // Expansion didn't work, we'll try to do a Full GC.
-    *gc_succeeded = do_collection(false, /* explicit_gc */
-                                  clear_all_soft_refs,
-                                  word_size);
+    *gc_succeeded = do_full_collection(false, /* explicit_gc */
+                                       clear_all_soft_refs);
   }
 
   return NULL;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -471,26 +471,20 @@
   void retire_gc_alloc_region(HeapRegion* alloc_region,
                               size_t allocated_bytes, InCSetState dest);
 
-  // - if explicit_gc is true, the GC is for a System.gc() or a heap
-  //   inspection request and should collect the entire heap
+  // - if explicit_gc is true, the GC is for a System.gc() etc,
+  //   otherwise it's for a failed allocation.
   // - if clear_all_soft_refs is true, all soft references should be
-  //   cleared during the GC
-  // - if explicit_gc is false, word_size describes the allocation that
-  //   the GC should attempt (at least) to satisfy
+  //   cleared during the GC.
   // - it returns false if it is unable to do the collection due to the
-  //   GC locker being active, true otherwise
-  bool do_collection(bool explicit_gc,
-                     bool clear_all_soft_refs,
-                     size_t word_size);
+  //   GC locker being active, true otherwise.
+  bool do_full_collection(bool explicit_gc,
+                          bool clear_all_soft_refs);
 
-  // Callback from VM_G1CollectFull operation.
-  // Perform a full collection.
+  // Callback from VM_G1CollectFull operation, or collect_as_vm_thread.
   virtual void do_full_collection(bool clear_all_soft_refs);
 
-  // Resize the heap if necessary after a full collection.  If this is
-  // after a collect-for allocation, "word_size" is the allocation size,
-  // and will be considered part of the used portion of the heap.
-  void resize_if_necessary_after_full_collection(size_t word_size);
+  // Resize the heap if necessary after a full collection.
+  void resize_if_necessary_after_full_collection();
 
   // Callback from VM_G1CollectForAllocation operation.
   // This function does everything necessary/possible to satisfy a
@@ -1150,9 +1144,6 @@
   // "CollectedHeap" supports.
   virtual void collect(GCCause::Cause cause);
 
-  // The same as above but assume that the caller holds the Heap_lock.
-  void collect_locked(GCCause::Cause cause);
-
   virtual bool copy_allocation_context_stats(const jint* contexts,
                                              jlong* totals,
                                              jbyte* accuracy,
@@ -1352,14 +1343,6 @@
     return (region_size / 2);
   }
 
-  // Update mod union table with the set of dirty cards.
-  void updateModUnion();
-
-  // Set the mod union bits corresponding to the given memRegion.  Note
-  // that this is always a safe operation, since it doesn't clear any
-  // bits.
-  void markModUnionRange(MemRegion mr);
-
   // Print the maximum heap capacity.
   virtual size_t max_capacity() const;
 
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -123,16 +123,13 @@
 
 template <G1Barrier barrier, G1Mark do_mark_object>
 class G1ParCopyClosure : public G1ParCopyHelper {
-private:
-  template <class T> void do_oop_work(T* p);
-
 public:
   G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
       G1ParCopyHelper(g1, par_scan_state) {
     assert(ref_processor() == NULL, "sanity");
   }
 
-  template <class T> void do_oop_nv(T* p) { do_oop_work(p); }
+  template <class T> void do_oop_nv(T* p);
   virtual void do_oop(oop* p)       { do_oop_nv(p); }
   virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
 };
--- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -251,7 +251,7 @@
 
 template <G1Barrier barrier, G1Mark do_mark_object>
 template <class T>
-void G1ParCopyClosure<barrier, do_mark_object>::do_oop_work(T* p) {
+void G1ParCopyClosure<barrier, do_mark_object>::do_oop_nv(T* p) {
   T heap_oop = oopDesc::load_heap_oop(p);
 
   if (oopDesc::is_null(heap_oop)) {
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -73,138 +73,111 @@
   FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl);
 }
 
-class ScanRSClosure : public HeapRegionClosure {
-  size_t _cards_done, _cards;
-  G1CollectedHeap* _g1h;
-
-  G1ParPushHeapRSClosure* _oc;
-  CodeBlobClosure* _code_root_cl;
-
-  G1BlockOffsetSharedArray* _bot_shared;
-  G1SATBCardTableModRefBS *_ct_bs;
-
-  double _strong_code_root_scan_time_sec;
-  uint   _worker_i;
-  size_t _block_size;
-  bool   _try_claimed;
-
-public:
-  ScanRSClosure(G1ParPushHeapRSClosure* oc,
-                CodeBlobClosure* code_root_cl,
-                uint worker_i) :
+ScanRSClosure::ScanRSClosure(G1ParPushHeapRSClosure* oc,
+                             CodeBlobClosure* code_root_cl,
+                             uint worker_i) :
     _oc(oc),
     _code_root_cl(code_root_cl),
     _strong_code_root_scan_time_sec(0.0),
     _cards(0),
     _cards_done(0),
     _worker_i(worker_i),
-    _try_claimed(false)
-  {
-    _g1h = G1CollectedHeap::heap();
-    _bot_shared = _g1h->bot_shared();
-    _ct_bs = _g1h->g1_barrier_set();
-    _block_size = MAX2<size_t>(G1RSetScanBlockSize, 1);
+    _try_claimed(false) {
+  _g1h = G1CollectedHeap::heap();
+  _bot_shared = _g1h->bot_shared();
+  _ct_bs = _g1h->g1_barrier_set();
+  _block_size = MAX2<size_t>(G1RSetScanBlockSize, 1);
+}
+
+void ScanRSClosure::scanCard(size_t index, HeapRegion *r) {
+  // Stack allocate the DirtyCardToOopClosure instance
+  HeapRegionDCTOC cl(_g1h, r, _oc,
+      CardTableModRefBS::Precise);
+
+  // Set the "from" region in the closure.
+  _oc->set_region(r);
+  MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
+  MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
+  MemRegion mr = pre_gc_allocated.intersection(card_region);
+  if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
+    // We make the card as "claimed" lazily (so races are possible
+    // but they're benign), which reduces the number of duplicate
+    // scans (the rsets of the regions in the cset can intersect).
+    _ct_bs->set_card_claimed(index);
+    _cards_done++;
+    cl.do_MemRegion(mr);
   }
+}
 
-  void set_try_claimed() { _try_claimed = true; }
+void ScanRSClosure::printCard(HeapRegion* card_region, size_t card_index,
+    HeapWord* card_start) {
+  gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
+      "RS names card " SIZE_FORMAT_HEX ": "
+      "[" PTR_FORMAT ", " PTR_FORMAT ")",
+      _worker_i,
+      p2i(card_region->bottom()), p2i(card_region->end()),
+      card_index,
+      p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words));
+}
 
-  void scanCard(size_t index, HeapRegion *r) {
-    // Stack allocate the DirtyCardToOopClosure instance
-    HeapRegionDCTOC cl(_g1h, r, _oc,
-                       CardTableModRefBS::Precise);
+void ScanRSClosure::scan_strong_code_roots(HeapRegion* r) {
+  double scan_start = os::elapsedTime();
+  r->strong_code_roots_do(_code_root_cl);
+  _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
+}
+
+bool ScanRSClosure::doHeapRegion(HeapRegion* r) {
+  assert(r->in_collection_set(), "should only be called on elements of CS.");
+  HeapRegionRemSet* hrrs = r->rem_set();
+  if (hrrs->iter_is_complete()) return false; // All done.
+  if (!_try_claimed && !hrrs->claim_iter()) return false;
+  // If we ever free the collection set concurrently, we should also
+  // clear the card table concurrently therefore we won't need to
+  // add regions of the collection set to the dirty cards region.
+  _g1h->push_dirty_cards_region(r);
+  // If we didn't return above, then
+  //   _try_claimed || r->claim_iter()
+  // is true: either we're supposed to work on claimed-but-not-complete
+  // regions, or we successfully claimed the region.
+
+  HeapRegionRemSetIterator iter(hrrs);
+  size_t card_index;
 
-    // Set the "from" region in the closure.
-    _oc->set_region(r);
-    MemRegion card_region(_bot_shared->address_for_index(index), G1BlockOffsetSharedArray::N_words);
-    MemRegion pre_gc_allocated(r->bottom(), r->scan_top());
-    MemRegion mr = pre_gc_allocated.intersection(card_region);
-    if (!mr.is_empty() && !_ct_bs->is_card_claimed(index)) {
-      // We make the card as "claimed" lazily (so races are possible
-      // but they're benign), which reduces the number of duplicate
-      // scans (the rsets of the regions in the cset can intersect).
-      _ct_bs->set_card_claimed(index);
-      _cards_done++;
-      cl.do_MemRegion(mr);
+  // We claim cards in block so as to reduce the contention. The block size is determined by
+  // the G1RSetScanBlockSize parameter.
+  size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
+  for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
+    if (current_card >= jump_to_card + _block_size) {
+      jump_to_card = hrrs->iter_claimed_next(_block_size);
+    }
+    if (current_card < jump_to_card) continue;
+    HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
+#if 0
+    gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
+        card_start, card_start + CardTableModRefBS::card_size_in_words);
+#endif
+
+    HeapRegion* card_region = _g1h->heap_region_containing(card_start);
+    _cards++;
+
+    if (!card_region->is_on_dirty_cards_region_list()) {
+      _g1h->push_dirty_cards_region(card_region);
+    }
+
+    // If the card is dirty, then we will scan it during updateRS.
+    if (!card_region->in_collection_set() &&
+        !_ct_bs->is_card_dirty(card_index)) {
+      scanCard(card_index, card_region);
     }
   }
-
-  void printCard(HeapRegion* card_region, size_t card_index,
-                 HeapWord* card_start) {
-    gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") "
-                           "RS names card " SIZE_FORMAT_HEX ": "
-                           "[" PTR_FORMAT ", " PTR_FORMAT ")",
-                           _worker_i,
-                           p2i(card_region->bottom()), p2i(card_region->end()),
-                           card_index,
-                           p2i(card_start), p2i(card_start + G1BlockOffsetSharedArray::N_words));
-  }
-
-  void scan_strong_code_roots(HeapRegion* r) {
-    double scan_start = os::elapsedTime();
-    r->strong_code_roots_do(_code_root_cl);
-    _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
-  }
-
-  bool doHeapRegion(HeapRegion* r) {
-    assert(r->in_collection_set(), "should only be called on elements of CS.");
-    HeapRegionRemSet* hrrs = r->rem_set();
-    if (hrrs->iter_is_complete()) return false; // All done.
-    if (!_try_claimed && !hrrs->claim_iter()) return false;
-    // If we ever free the collection set concurrently, we should also
-    // clear the card table concurrently therefore we won't need to
-    // add regions of the collection set to the dirty cards region.
-    _g1h->push_dirty_cards_region(r);
-    // If we didn't return above, then
-    //   _try_claimed || r->claim_iter()
-    // is true: either we're supposed to work on claimed-but-not-complete
-    // regions, or we successfully claimed the region.
-
-    HeapRegionRemSetIterator iter(hrrs);
-    size_t card_index;
+  if (!_try_claimed) {
+    // Scan the strong code root list attached to the current region
+    scan_strong_code_roots(r);
 
-    // We claim cards in block so as to reduce the contention. The block size is determined by
-    // the G1RSetScanBlockSize parameter.
-    size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
-    for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
-      if (current_card >= jump_to_card + _block_size) {
-        jump_to_card = hrrs->iter_claimed_next(_block_size);
-      }
-      if (current_card < jump_to_card) continue;
-      HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
-#if 0
-      gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
-                          card_start, card_start + CardTableModRefBS::card_size_in_words);
-#endif
-
-      HeapRegion* card_region = _g1h->heap_region_containing(card_start);
-      _cards++;
-
-      if (!card_region->is_on_dirty_cards_region_list()) {
-        _g1h->push_dirty_cards_region(card_region);
-      }
-
-      // If the card is dirty, then we will scan it during updateRS.
-      if (!card_region->in_collection_set() &&
-          !_ct_bs->is_card_dirty(card_index)) {
-        scanCard(card_index, card_region);
-      }
-    }
-    if (!_try_claimed) {
-      // Scan the strong code root list attached to the current region
-      scan_strong_code_roots(r);
-
-      hrrs->set_iter_complete();
-    }
-    return false;
+    hrrs->set_iter_complete();
   }
-
-  double strong_code_root_scan_time_sec() {
-    return _strong_code_root_scan_time_sec;
-  }
-
-  size_t cards_done() { return _cards_done;}
-  size_t cards_looked_up() { return _cards;}
-};
+  return false;
+}
 
 size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
                         CodeBlobClosure* heap_region_codeblobs,
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -156,6 +156,41 @@
   }
 };
 
+class ScanRSClosure : public HeapRegionClosure {
+  size_t _cards_done, _cards;
+  G1CollectedHeap* _g1h;
+
+  G1ParPushHeapRSClosure* _oc;
+  CodeBlobClosure* _code_root_cl;
+
+  G1BlockOffsetSharedArray* _bot_shared;
+  G1SATBCardTableModRefBS *_ct_bs;
+
+  double _strong_code_root_scan_time_sec;
+  uint   _worker_i;
+  size_t _block_size;
+  bool   _try_claimed;
+
+public:
+  ScanRSClosure(G1ParPushHeapRSClosure* oc,
+                CodeBlobClosure* code_root_cl,
+                uint worker_i);
+
+  bool doHeapRegion(HeapRegion* r);
+
+  double strong_code_root_scan_time_sec() {
+    return _strong_code_root_scan_time_sec;
+  }
+  size_t cards_done() { return _cards_done;}
+  size_t cards_looked_up() { return _cards;}
+  void set_try_claimed() { _try_claimed = true; }
+private:
+  void scanCard(size_t index, HeapRegion *r);
+  void printCard(HeapRegion* card_region, size_t card_index,
+                 HeapWord* card_start);
+  void scan_strong_code_roots(HeapRegion* r);
+};
+
 class UpdateRSOopClosure: public ExtendedOopClosure {
   HeapRegion* _from;
   G1RemSet* _rs;
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -211,14 +211,14 @@
   _gc_efficiency = (double) reclaimable_bytes() / region_elapsed_time_ms;
 }
 
-void HeapRegion::set_starts_humongous(HeapWord* obj_top) {
+void HeapRegion::set_starts_humongous(HeapWord* obj_top, size_t fill_size) {
   assert(!is_humongous(), "sanity / pre-condition");
   assert(top() == bottom(), "should be empty");
 
   _type.set_starts_humongous();
   _humongous_start_region = this;
 
-  _offsets.set_for_starts_humongous(obj_top);
+  _offsets.set_for_starts_humongous(obj_top, fill_size);
 }
 
 void HeapRegion::set_continues_humongous(HeapRegion* first_hr) {
@@ -756,16 +756,6 @@
     size_t obj_size = block_size(p);
     object_num += 1;
 
-    if (is_region_humongous != g1->is_humongous(obj_size) &&
-        !g1->is_obj_dead(obj, this)) { // Dead objects may have bigger block_size since they span several objects.
-      gclog_or_tty->print_cr("obj " PTR_FORMAT " is of %shumongous size ("
-                             SIZE_FORMAT " words) in a %shumongous region",
-                             p2i(p), g1->is_humongous(obj_size) ? "" : "non-",
-                             obj_size, is_region_humongous ? "" : "non-");
-       *failures = true;
-       return;
-    }
-
     if (!g1->is_obj_dead_cond(obj, this, vo)) {
       if (obj->is_oop()) {
         Klass* klass = obj->klass();
@@ -876,14 +866,6 @@
     }
   }
 
-  if (is_region_humongous && object_num > 1) {
-    gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] is humongous "
-                           "but has " SIZE_FORMAT ", objects",
-                           p2i(bottom()), p2i(end()), object_num);
-    *failures = true;
-    return;
-  }
-
   verify_strong_code_roots(vo, failures);
 }
 
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -455,9 +455,9 @@
   // the first region in a series of one or more contiguous regions
   // that will contain a single "humongous" object.
   //
-  // obj_top : points to the end of the humongous object that's being
-  // allocated.
-  void set_starts_humongous(HeapWord* obj_top);
+  // obj_top : points to the top of the humongous object.
+  // fill_size : size of the filler object at the end of the region series.
+  void set_starts_humongous(HeapWord* obj_top, size_t fill_size);
 
   // Makes the current region be a "continues humongous'
   // region. first_hr is the "start humongous" region of the series
--- a/hotspot/src/share/vm/logging/log.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/logging/log.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -37,10 +37,10 @@
 
   // Write long message to output file
   MutexLocker ml(LogConfiguration_lock);
-  LogConfiguration::parse_log_arguments("loglengthoutput.txt", "logging=develop",
+  LogConfiguration::parse_log_arguments("loglengthoutput.txt", "logging=trace",
     NULL, NULL, NULL);
   ResourceMark rm;
-  outputStream* logstream = LogHandle(logging)::develop_stream();
+  outputStream* logstream = LogHandle(logging)::trace_stream();
   logstream->print_cr("01:1234567890-"
                       "02:1234567890-"
                       "03:1234567890-"
--- a/hotspot/src/share/vm/logging/log.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/logging/log.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -49,11 +49,21 @@
 #define log_info(...)    (!log_is_enabled(Info, __VA_ARGS__))    ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info>
 #define log_debug(...)   (!log_is_enabled(Debug, __VA_ARGS__))   ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug>
 #define log_trace(...)   (!log_is_enabled(Trace, __VA_ARGS__))   ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace>
+
+// Macros for logging that should be excluded in product builds.
+// Available for levels Info, Debug and Trace. Includes test macro that
+// evaluates to false in product builds.
 #ifndef PRODUCT
-#define log_develop(...) (!log_is_enabled(Develop, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Develop>
+#define log_develop_info(...)  (!log_is_enabled(Info, __VA_ARGS__))   ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Info>
+#define log_develop_debug(...) (!log_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Debug>
+#define log_develop_trace(...) (!log_is_enabled(Trace, __VA_ARGS__))  ? (void)0 : Log<LOG_TAGS(__VA_ARGS__)>::write<LogLevel::Trace>
+#define develop_log_is_enabled(level, ...)  log_is_enabled(level, __VA_ARGS__)
 #else
 #define DUMMY_ARGUMENT_CONSUMER(...)
-#define log_develop(...) DUMMY_ARGUMENT_CONSUMER
+#define log_develop_info(...)  DUMMY_ARGUMENT_CONSUMER
+#define log_develop_debug(...) DUMMY_ARGUMENT_CONSUMER
+#define log_develop_trace(...) DUMMY_ARGUMENT_CONSUMER
+#define develop_log_is_enabled(...)  false
 #endif
 
 // Convenience macro to test if the logging is enabled on the specified level for given tags.
@@ -88,6 +98,11 @@
   // is not __NO_TAG, the number of tags given exceeds the maximum allowed.
   STATIC_ASSERT(GuardTag == LogTag::__NO_TAG); // Number of logging tags exceeds maximum supported!
 
+  // Empty constructor to avoid warnings on MSVC about unused variables
+  // when the log instance is only used for static functions.
+  Log() {
+  }
+
   static bool is_level(LogLevelType level) {
     return LogTagSetMapping<T0, T1, T2, T3, T4>::tagset().is_level(level);
   }
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -44,6 +44,7 @@
   LogDiagnosticCommand::registerCommand();
   LogHandle(logging) log;
   log.info("Log configuration fully initialized.");
+  log_develop_info(logging)("Develop logging is available.");
   if (log.is_trace()) {
     ResourceMark rm;
     MutexLocker ml(LogConfiguration_lock);
--- a/hotspot/src/share/vm/logging/logLevel.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/logging/logLevel.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -29,14 +29,8 @@
 
 // The list of log levels:
 //
-//  develop - A non-product level that is finer than trace.
-//            Should be used for really expensive and/or
-//            extensive logging, or logging that shouldn't
-//            or can't be included in a product build.
-//
-//  trace   - Finest level of logging in product builds.
-//            Use for extensive/noisy logging that can
-//            give slow-down when enabled.
+//  trace   - Finest level of logging. Use for extensive/noisy
+//            logging that can give slow-down when enabled.
 //
 //  debug   - A finer level of logging. Use for semi-noisy
 //            logging that is does not fit the info level.
@@ -49,7 +43,6 @@
 //  error   - Critical messages caused by errors.
 //
 #define LOG_LEVEL_LIST \
-  NOT_PRODUCT(LOG_LEVEL(Develop, develop)) \
   LOG_LEVEL(Trace, trace) \
   LOG_LEVEL(Debug, debug) \
   LOG_LEVEL(Info, info) \
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -3230,36 +3230,6 @@
     SharedMiscDataSize  = align_size_up(SharedMiscDataSize,  max_alignment);
     SharedMiscCodeSize  = align_size_up(SharedMiscCodeSize,  max_alignment);
 
-    // make sure SharedReadOnlySize and SharedReadWriteSize are not less than
-    // the minimum values.
-    if (SharedReadOnlySize < MetaspaceShared::min_ro_size){
-      report_out_of_shared_space(SharedReadOnly);
-    }
-
-    if (SharedReadWriteSize < MetaspaceShared::min_rw_size){
-      report_out_of_shared_space(SharedReadWrite);
-    }
-
-    // the min_misc_data_size and min_misc_code_size estimates are based on
-    // MetaspaceShared::generate_vtable_methods().
-    // The minimum size only accounts for the vtable methods. Any size less than the
-    // minimum required size would cause vm crash when allocating the vtable methods.
-    uint min_misc_data_size = align_size_up(
-      MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size * sizeof(void*), max_alignment);
-
-    if (SharedMiscDataSize < min_misc_data_size) {
-      report_out_of_shared_space(SharedMiscData);
-    }
-
-    uintx min_misc_code_size = align_size_up(
-      (MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size) *
-        (sizeof(void*) + MetaspaceShared::vtbl_method_size) + MetaspaceShared::vtbl_common_code_size,
-          max_alignment);
-
-    if (SharedMiscCodeSize < min_misc_code_size) {
-      report_out_of_shared_space(SharedMiscCode);
-    }
-
     // Initialize with the sum of the shared space sizes.  The read-only
     // and read write metaspace chunks will be allocated out of this and the
     // remainder is the misc code and data chunks.
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -32,14 +32,55 @@
 #include "utilities/exceptions.hpp"
 #include "utilities/macros.hpp"
 
-#define LargeSharedArchiveSize    (300*M)
-#define HugeSharedArchiveSize     (800*M)
-#define ReadOnlyRegionPercentage  0.4
-#define ReadWriteRegionPercentage 0.55
-#define MiscDataRegionPercentage  0.03
-#define MiscCodeRegionPercentage  0.02
-#define LargeThresholdClassCount  5000
-#define HugeThresholdClassCount   40000
+#define DEFAULT_VTBL_LIST_SIZE          (17)  // number of entries in the shared space vtable list.
+#define DEFAULT_VTBL_VIRTUALS_COUNT     (200) // maximum number of virtual functions
+// If virtual functions are added to Metadata,
+// this number needs to be increased.  Also,
+// SharedMiscCodeSize will need to be increased.
+// The following 2 sizes were based on
+// MetaspaceShared::generate_vtable_methods()
+#define DEFAULT_VTBL_METHOD_SIZE        (16)  // conservative size of the mov1 and jmp instructions
+// for the x64 platform
+#define DEFAULT_VTBL_COMMON_CODE_SIZE   (1*K) // conservative size of the "common_code" for the x64 platform
+
+#define DEFAULT_SHARED_READ_WRITE_SIZE  (NOT_LP64(12*M) LP64_ONLY(16*M))
+#define MIN_SHARED_READ_WRITE_SIZE      (NOT_LP64(7*M) LP64_ONLY(12*M))
+
+#define DEFAULT_SHARED_READ_ONLY_SIZE   (NOT_LP64(12*M) LP64_ONLY(16*M))
+#define MIN_SHARED_READ_ONLY_SIZE       (NOT_LP64(8*M) LP64_ONLY(9*M))
+
+// the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on
+// MetaspaceShared::generate_vtable_methods().
+// The minimum size only accounts for the vtable methods. Any size less than the
+// minimum required size would cause vm crash when allocating the vtable methods.
+#define SHARED_MISC_SIZE_FOR(size)      (DEFAULT_VTBL_VIRTUALS_COUNT*DEFAULT_VTBL_LIST_SIZE*size)
+
+#define DEFAULT_SHARED_MISC_DATA_SIZE   (NOT_LP64(2*M) LP64_ONLY(4*M))
+#define MIN_SHARED_MISC_DATA_SIZE       (SHARED_MISC_SIZE_FOR(sizeof(void*)))
+
+#define DEFAULT_SHARED_MISC_CODE_SIZE   (120*K)
+#define MIN_SHARED_MISC_CODE_SIZE       (SHARED_MISC_SIZE_FOR(sizeof(void*))+SHARED_MISC_SIZE_FOR(DEFAULT_VTBL_METHOD_SIZE)+DEFAULT_VTBL_COMMON_CODE_SIZE)
+
+#define DEFAULT_COMBINED_SIZE           (DEFAULT_SHARED_READ_WRITE_SIZE+DEFAULT_SHARED_READ_ONLY_SIZE+DEFAULT_SHARED_MISC_DATA_SIZE+DEFAULT_SHARED_MISC_CODE_SIZE)
+
+// the max size is the MAX size (ie. 0x7FFFFFFF) - the total size of
+// the other 3 sections - page size (to avoid overflow in case the final
+// size will get aligned up on page size)
+#define SHARED_PAGE                     ((size_t)os::vm_page_size())
+#define MAX_SHARED_DELTA                (0x7FFFFFFF)
+#define MAX_SHARED_READ_WRITE_SIZE      (MAX_SHARED_DELTA-(MIN_SHARED_READ_ONLY_SIZE+MIN_SHARED_MISC_DATA_SIZE+MIN_SHARED_MISC_CODE_SIZE)-SHARED_PAGE)
+#define MAX_SHARED_READ_ONLY_SIZE       (MAX_SHARED_DELTA-(MIN_SHARED_READ_WRITE_SIZE+MIN_SHARED_MISC_DATA_SIZE+MIN_SHARED_MISC_CODE_SIZE)-SHARED_PAGE)
+#define MAX_SHARED_MISC_DATA_SIZE       (MAX_SHARED_DELTA-(MIN_SHARED_READ_WRITE_SIZE+MIN_SHARED_READ_ONLY_SIZE+MIN_SHARED_MISC_CODE_SIZE)-SHARED_PAGE)
+#define MAX_SHARED_MISC_CODE_SIZE       (MAX_SHARED_DELTA-(MIN_SHARED_READ_WRITE_SIZE+MIN_SHARED_READ_ONLY_SIZE+MIN_SHARED_MISC_DATA_SIZE)-SHARED_PAGE)
+
+#define LargeSharedArchiveSize          (300*M)
+#define HugeSharedArchiveSize           (800*M)
+#define ReadOnlyRegionPercentage        0.4
+#define ReadWriteRegionPercentage       0.55
+#define MiscDataRegionPercentage        0.03
+#define MiscCodeRegionPercentage        0.02
+#define LargeThresholdClassCount        5000
+#define HugeThresholdClassCount         40000
 
 #define SET_ESTIMATED_SIZE(type, region)                              \
   Shared ##region## Size  = FLAG_IS_DEFAULT(Shared ##region## Size) ? \
@@ -69,21 +110,10 @@
   static bool _archive_loading_failed;
  public:
   enum {
-    vtbl_list_size         = 17,   // number of entries in the shared space vtable list.
-    num_virtuals           = 200,  // maximum number of virtual functions
-                                   // If virtual functions are added to Metadata,
-                                   // this number needs to be increased.  Also,
-                                   // SharedMiscCodeSize will need to be increased.
-                                   // The following 2 sizes were based on
-                                   // MetaspaceShared::generate_vtable_methods()
-    vtbl_method_size       = 16,   // conservative size of the mov1 and jmp instructions
-                                   // for the x64 platform
-    vtbl_common_code_size  = (1*K) // conservative size of the "common_code" for the x64 platform
-  };
-
-  enum {
-    min_ro_size = NOT_LP64(8*M) LP64_ONLY(9*M), // minimum ro and rw regions sizes based on dumping
-    min_rw_size = NOT_LP64(7*M) LP64_ONLY(12*M) // of a shared archive using the default classlist
+    vtbl_list_size         = DEFAULT_VTBL_LIST_SIZE,
+    num_virtuals           = DEFAULT_VTBL_VIRTUALS_COUNT,
+    vtbl_method_size       = DEFAULT_VTBL_METHOD_SIZE,
+    vtbl_common_code_size  = DEFAULT_VTBL_COMMON_CODE_SIZE
   };
 
   enum {
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -223,7 +223,7 @@
 #define EMIT_CONSTRAINT_CHECK(func, type)                               , func, CommandLineFlagConstraint::type
 
 // the "name" argument must be a string literal
-#define INITIAL_CONSTRAINTS_SIZE 45
+#define INITIAL_CONSTRAINTS_SIZE 69
 GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
 CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse;
 
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp	Mon Nov 23 14:38:20 2015 -0500
@@ -279,7 +279,7 @@
 // Generate func argument to pass into emit_range_xxx functions
 #define EMIT_RANGE_CHECK(a, b)                               , a, b
 
-#define INITIAL_RANGES_SIZE 205
+#define INITIAL_RANGES_SIZE 320
 GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
 
 // Check the ranges of all flags that have them
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
 #define SHARE_VM_RUNTIME_COMMANDLINEFLAGRANGELIST_HPP
 
+#include "memory/metaspaceShared.hpp"
 #include "runtime/globals.hpp"
 #include "utilities/growableArray.hpp"
 
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Mon Nov 23 14:38:20 2015 -0500
@@ -4110,21 +4110,26 @@
           "If PrintSharedArchiveAndExit is true, also print the shared "    \
           "dictionary")                                                     \
                                                                             \
-  product(size_t, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M),      \
+  product(size_t, SharedReadWriteSize, DEFAULT_SHARED_READ_WRITE_SIZE,      \
           "Size of read-write space for metadata (in bytes)")               \
-                                                                            \
-  product(size_t, SharedReadOnlySize, NOT_LP64(12*M) LP64_ONLY(16*M),       \
+          range(MIN_SHARED_READ_WRITE_SIZE, MAX_SHARED_READ_WRITE_SIZE)     \
+                                                                            \
+  product(size_t, SharedReadOnlySize, DEFAULT_SHARED_READ_ONLY_SIZE,        \
           "Size of read-only space for metadata (in bytes)")                \
-                                                                            \
-  product(uintx, SharedMiscDataSize,    NOT_LP64(2*M) LP64_ONLY(4*M),       \
+          range(MIN_SHARED_READ_ONLY_SIZE, MAX_SHARED_READ_ONLY_SIZE)       \
+                                                                            \
+  product(size_t, SharedMiscDataSize, DEFAULT_SHARED_MISC_DATA_SIZE,        \
           "Size of the shared miscellaneous data area (in bytes)")          \
-                                                                            \
-  product(uintx, SharedMiscCodeSize,    120*K,                              \
+          range(MIN_SHARED_MISC_DATA_SIZE, MAX_SHARED_MISC_DATA_SIZE)       \
+                                                                            \
+  product(size_t, SharedMiscCodeSize, DEFAULT_SHARED_MISC_CODE_SIZE,        \
           "Size of the shared miscellaneous code area (in bytes)")          \
-                                                                            \
-  product(uintx, SharedBaseAddress, LP64_ONLY(32*G)                         \
+          range(MIN_SHARED_MISC_CODE_SIZE, MAX_SHARED_MISC_CODE_SIZE)       \
+                                                                            \
+  product(size_t, SharedBaseAddress, LP64_ONLY(32*G)                        \
           NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)),                           \
           "Address to allocate shared memory region for class data")        \
+          range(0, SIZE_MAX)                                                \
                                                                             \
   product(uintx, SharedSymbolTableBucketSize, 4,                            \
           "Average number of symbols per bucket in shared table")           \
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Mon Nov 23 14:38:20 2015 -0500
@@ -55,10 +55,29 @@
          * JDK-8136766
          * Temporarily remove ThreadStackSize from testing because Windows can set it to 0
          * (for default OS size) but other platforms insist it must be greater than 0
-        */
+         */
         allOptionsAsMap.remove("ThreadStackSize");
 
         /*
+         * JDK-8141650
+         * Temporarily exclude SharedMiscDataSize as it will exit the VM with exit code 2 and
+         * "The shared miscellaneous data space is not large enough to preload requested classes."
+         * message at min value.
+         */
+        allOptionsAsMap.remove("SharedMiscDataSize");
+
+        /*
+         * JDK-8142874
+         * Temporarily exclude Shared* flagse as they will exit the VM with exit code 2 and
+         * "The shared miscellaneous data space is not large enough to preload requested classes."
+         * message at max values.
+         */
+        allOptionsAsMap.remove("SharedReadWriteSize");
+        allOptionsAsMap.remove("SharedReadOnlySize");
+        allOptionsAsMap.remove("SharedMiscDataSize");
+        allOptionsAsMap.remove("SharedMiscCodeSize");
+
+        /*
          * Exclude MallocMaxTestWords as it is expected to exit VM at small values (>=0)
          */
         allOptionsAsMap.remove("MallocMaxTestWords");
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/IntJVMOption.java	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/IntJVMOption.java	Mon Nov 23 14:38:20 2015 -0500
@@ -223,7 +223,7 @@
             validValues.add("1");
         }
 
-        if (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1) {
+        if ((min.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == -1) && (max.compareTo(MAX_4_BYTE_INT_PLUS_ONE) == 1)) {
             /*
              * Check for overflow when flag is assigned to the
              * 4 byte int variable
@@ -231,7 +231,7 @@
             validValues.add(MAX_4_BYTE_INT_PLUS_ONE.toString());
         }
 
-        if (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1) {
+        if ((min.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == -1) && (max.compareTo(MAX_4_BYTE_UNSIGNED_INT_PLUS_ONE) == 1)) {
             /*
              * Check for overflow when flag is assigned to the
              * 4 byte unsigned int variable
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java	Mon Nov 23 14:38:20 2015 -0500
@@ -27,6 +27,7 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -49,6 +50,8 @@
     /* Used to start the JVM with the same type as current */
     static String VMType;
 
+    private static Map<String, JVMOption> optionsAsMap;
+
     static {
         if (Platform.isServer()) {
             VMType = "-server";
@@ -63,6 +66,84 @@
         }
     }
 
+    public static boolean fitsRange(String optionName, BigDecimal number) throws Exception {
+        JVMOption option;
+        String minRangeString = null;
+        String maxRangeString = null;
+        boolean fits = true;
+
+        if (optionsAsMap == null) {
+            optionsAsMap = getOptionsWithRangeAsMap();
+        }
+
+        option = optionsAsMap.get(optionName);
+        if (option != null) {
+            minRangeString = option.getMin();
+            if (minRangeString != null) {
+                fits = (number.compareTo(new BigDecimal(minRangeString)) >= 0);
+            }
+            maxRangeString = option.getMax();
+            if (maxRangeString != null) {
+                fits &= (number.compareTo(new BigDecimal(maxRangeString)) <= 0);
+            }
+        }
+
+        return fits;
+    }
+
+    public static boolean fitsRange(String optionName, String number) throws Exception {
+        String lowerCase = number.toLowerCase();
+        String multiplier = "1";
+        if (lowerCase.endsWith("k")) {
+            multiplier = "1024";
+            lowerCase = lowerCase.substring(0, lowerCase.length()-1);
+        } else if (lowerCase.endsWith("m")) {
+            multiplier = "1048576"; //1024*1024
+            lowerCase = lowerCase.substring(0, lowerCase.length()-1);
+        } else if (lowerCase.endsWith("g")) {
+            multiplier = "1073741824"; //1024*1024*1024
+            lowerCase = lowerCase.substring(0, lowerCase.length()-1);
+        } else if (lowerCase.endsWith("t")) {
+            multiplier = "1099511627776"; //1024*1024*1024*1024
+            lowerCase = lowerCase.substring(0, lowerCase.length()-1);
+        }
+        BigDecimal valueBig = new BigDecimal(lowerCase);
+        BigDecimal multiplierBig = new BigDecimal(multiplier);
+        return fitsRange(optionName, valueBig.multiply(multiplierBig));
+    }
+
+    public static String getMinOptionRange(String optionName) throws Exception {
+        JVMOption option;
+        String minRange = null;
+
+        if (optionsAsMap == null) {
+            optionsAsMap = getOptionsWithRangeAsMap();
+        }
+
+        option = optionsAsMap.get(optionName);
+        if (option != null) {
+            minRange = option.getMin();
+        }
+
+        return minRange;
+    }
+
+    public static String getMaxOptionRange(String optionName) throws Exception {
+        JVMOption option;
+        String maxRange = null;
+
+        if (optionsAsMap == null) {
+            optionsAsMap = getOptionsWithRangeAsMap();
+        }
+
+        option = optionsAsMap.get(optionName);
+        if (option != null) {
+            maxRange = option.getMax();
+        }
+
+        return maxRange;
+    }
+
     /**
      * Add dependency for option depending on it's name. E.g. enable G1 GC for
      * G1 options or add prepend options to not hit constraints.
@@ -80,6 +161,13 @@
             option.addPrepend("-XX:+UseConcMarkSweepGC");
         }
 
+        if (name.startsWith("Shared")) {
+            option.addPrepend("-XX:+UnlockDiagnosticVMOptions");
+            String fileName = "Test" + name + ".jsa";
+            option.addPrepend("-XX:SharedArchiveFile=" + fileName);
+            option.addPrepend("-Xshare:dump");
+        }
+
         switch (name) {
             case "MinHeapFreeRatio":
                 option.addPrepend("-XX:MaxHeapFreeRatio=100");
@@ -112,7 +200,6 @@
                 /* Do nothing */
                 break;
         }
-
     }
 
     /**
--- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java	Thu Nov 19 19:26:51 2015 -0500
+++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java	Mon Nov 23 14:38:20 2015 -0500
@@ -23,50 +23,72 @@
 
 /* @test LimitSharedSizes
  * @summary Test handling of limits on shared space size
- * @library /testlibrary
+ * @library /testlibrary /runtime/CommandLine/OptionsValidation/common
  * @modules java.base/sun.misc
  *          java.management
  * @run main LimitSharedSizes
  */
 
 import jdk.test.lib.*;
+import optionsvalidation.JVMOptionsUtils;
 
 public class LimitSharedSizes {
+    static enum Result {
+        OUT_OF_RANGE,
+        TOO_SMALL,
+        VALID,
+        VALID_ARCHIVE
+    }
+
     static enum Region {
         RO, RW, MD, MC
     }
 
+    private static final boolean fitsRange(String name, String value) throws RuntimeException {
+        boolean fits = true;
+        try {
+            fits = JVMOptionsUtils.fitsRange(name, value);
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
+        return fits;
+    }
+
     private static class SharedSizeTestData {
         public String optionName;
         public String optionValue;
-        public String expectedErrorMsg;
+        public Result optionResult;
 
-        public SharedSizeTestData(Region region, String value, String msg) {
-            optionName = getName(region);
+        public SharedSizeTestData(Region region, String value) {
+            optionName = "-XX:"+getName(region);
             optionValue = value;
-            expectedErrorMsg = msg;
+            if (fitsRange(getName(region), value) == false) {
+                optionResult = Result.OUT_OF_RANGE;
+            } else {
+                optionResult = Result.TOO_SMALL;
+            }
         }
 
-        public SharedSizeTestData(Region region, String msg) {
-            optionName = getName(region);
-            optionValue = getValue(region);
-            expectedErrorMsg = msg;
+        public SharedSizeTestData(Region region, String value, Result result) {
+            optionName = "-XX:"+getName(region);
+            optionValue = value;
+            optionResult = result;
         }
 
         private String getName(Region region) {
             String name;
             switch (region) {
                 case RO:
-                    name = "-XX:SharedReadOnlySize";
+                    name = "SharedReadOnlySize";
                     break;
                 case RW:
-                    name = "-XX:SharedReadWriteSize";
+                    name = "SharedReadWriteSize";
                     break;
                 case MD:
-                    name = "-XX:SharedMiscDataSize";
+                    name = "SharedMiscDataSize";
                     break;
                 case MC:
-                    name = "-XX:SharedMiscCodeSize";
+                    name = "SharedMiscCodeSize";
                     break;
                 default:
                     name = "Unknown";
@@ -75,53 +97,37 @@
             return name;
         }
 
-        private String getValue(Region region) {
-            String value;
-            switch (region) {
-                case RO:
-                    value = Platform.is64bit() ? "9M" : "8M";
-                    break;
-                case RW:
-                    value = Platform.is64bit() ? "12M" : "7M";
-                    break;
-                case MD:
-                    value = Platform.is64bit() ? "4M" : "2M";
-                    break;
-                case MC:
-                    value = "120k";
-                    break;
-                default:
-                    value = "0M";
-                    break;
-            }
-            return value;
+        public Result getResult() {
+            return optionResult;
         }
     }
 
     private static final SharedSizeTestData[] testTable = {
         // Too small of a region size should not cause a vm crash.
-        // It should result in an error message like the following:
+        // It should result in an error message either like the following #1:
         // The shared miscellaneous code space is not large enough
         // to preload requested classes. Use -XX:SharedMiscCodeSize=
         // to increase the initial size of shared miscellaneous code space.
-        new SharedSizeTestData(Region.RO, "4M",   "read only"),
-        new SharedSizeTestData(Region.RW, "4M",   "read write"),
-        new SharedSizeTestData(Region.MD, "50k",  "miscellaneous data"),
-        new SharedSizeTestData(Region.MC, "20k",  "miscellaneous code"),
+        // or #2:
+        // The shared miscellaneous code space is outside the allowed range
+        new SharedSizeTestData(Region.RO, "4M"),
+        new SharedSizeTestData(Region.RW, "4M"),
+        new SharedSizeTestData(Region.MD, "50k"),
+        new SharedSizeTestData(Region.MC, "20k"),
 
-        // these values are larger than default ones, but should
+        // these values are larger than default ones, and should
         // be acceptable and not cause failure
-        new SharedSizeTestData(Region.RO, "20M", null),
-        new SharedSizeTestData(Region.RW, "20M", null),
-        new SharedSizeTestData(Region.MD, "20M", null),
-        new SharedSizeTestData(Region.MC, "20M", null),
+        new SharedSizeTestData(Region.RO, "20M", Result.VALID),
+        new SharedSizeTestData(Region.RW, "20M", Result.VALID),
+        new SharedSizeTestData(Region.MD, "20M", Result.VALID),
+        new SharedSizeTestData(Region.MC, "20M", Result.VALID),
 
         // test with sizes which just meet the minimum required sizes
         // the following tests also attempt to use the shared archive
-        new SharedSizeTestData(Region.RO, "UseArchive"),
-        new SharedSizeTestData(Region.RW, "UseArchive"),
-        new SharedSizeTestData(Region.MD, "UseArchive"),
-        new SharedSizeTestData(Region.MC, "UseArchive")
+        new SharedSizeTestData(Region.RO, Platform.is64bit() ? "9M":"8M", Result.VALID_ARCHIVE),
+        new SharedSizeTestData(Region.RW, Platform.is64bit() ? "12M":"7M", Result.VALID_ARCHIVE),
+        new SharedSizeTestData(Region.MD, Platform.is64bit() ? "4M":"2M", Result.VALID_ARCHIVE),
+        new SharedSizeTestData(Region.MC, "120k", Result.VALID_ARCHIVE),
     };
 
     public static void main(String[] args) throws Exception {
@@ -131,6 +137,7 @@
             counter++;
 
             String option = td.optionName + "=" + td.optionValue;
+            System.out.println("testing option number <" + counter + ">");
             System.out.println("testing option <" + option + ">");
 
             ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
@@ -141,43 +148,52 @@
 
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
 
-            if (td.expectedErrorMsg != null) {
-                if (!td.expectedErrorMsg.equals("UseArchive")) {
-                    output.shouldContain("The shared " + td.expectedErrorMsg
-                        + " space is not large enough");
+            switch (td.getResult()) {
+                case VALID:
+                case VALID_ARCHIVE:
+                {
+                  output.shouldNotContain("space is not large enough");
+                  output.shouldHaveExitValue(0);
 
-                    output.shouldHaveExitValue(2);
-                } else {
-                    output.shouldNotContain("space is not large enough");
-                    output.shouldHaveExitValue(0);
-
-                    // try to use the archive
-                    pb = ProcessTools.createJavaProcessBuilder(
-                       "-XX:+UnlockDiagnosticVMOptions",
-                       "-XX:SharedArchiveFile=./" + fileName,
-                       "-XX:+PrintSharedArchiveAndExit",
-                       "-version");
+                  if (td.getResult() == Result.VALID_ARCHIVE) {
+                      // try to use the archive
+                      pb = ProcessTools.createJavaProcessBuilder(
+                         "-XX:+UnlockDiagnosticVMOptions",
+                         "-XX:SharedArchiveFile=./" + fileName,
+                         "-XX:+PrintSharedArchiveAndExit",
+                         "-version");
 
-                    try {
-                        output = new OutputAnalyzer(pb.start());
-                        output.shouldContain("archive is valid");
-                    } catch (RuntimeException e) {
-                        // if sharing failed due to ASLR or similar reasons,
-                        // check whether sharing was attempted at all (UseSharedSpaces)
-                        if ((output.getOutput().contains("Unable to use shared archive") ||
-                             output.getOutput().contains("Unable to map ReadOnly shared space at required address.") ||
-                             output.getOutput().contains("Unable to map ReadWrite shared space at required address.") ||
-                             output.getOutput().contains("Unable to reserve shared space at required address")) &&
-                             output.getExitValue() == 1) {
-                             System.out.println("Unable to use shared archive: test not executed; assumed passed");
-                             return;
-                        }
-                    }
-                    output.shouldHaveExitValue(0);
+                      try {
+                          output = new OutputAnalyzer(pb.start());
+                          output.shouldContain("archive is valid");
+                      } catch (RuntimeException e) {
+                          // if sharing failed due to ASLR or similar reasons,
+                          // check whether sharing was attempted at all (UseSharedSpaces)
+                          if ((output.getOutput().contains("Unable to use shared archive") ||
+                               output.getOutput().contains("Unable to map ReadOnly shared space at required address.") ||
+                               output.getOutput().contains("Unable to map ReadWrite shared space at required address.") ||
+                               output.getOutput().contains("Unable to reserve shared space at required address")) &&
+                               output.getExitValue() == 1) {
+                               System.out.println("Unable to use shared archive: test not executed; assumed passed");
+                               return;
+                          }
+                      }
+                      output.shouldHaveExitValue(0);
+                  }
                 }
-            } else {
-                output.shouldNotContain("space is not large enough");
-                output.shouldHaveExitValue(0);
+                break;
+                case TOO_SMALL:
+                {
+                    output.shouldContain("space is not large enough");
+                    output.shouldHaveExitValue(2);
+                }
+                break;
+                case OUT_OF_RANGE:
+                {
+                    output.shouldContain("outside the allowed range");
+                    output.shouldHaveExitValue(1);
+                }
+                break;
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ThreadSignalMask/Prog.java	Mon Nov 23 14:38:20 2015 -0500
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class Prog {
+
+    public static void main(String args[]) {
+        System.out.println("Java class invoked: " + args[0]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ThreadSignalMask/ThreadSignalMask.java	Mon Nov 23 14:38:20 2015 -0500
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.ProcessBuilder.Redirect;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.List;
+import jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @key cte_test
+ * @bug 4345157
+ * @summary JDK 1.3.0 alters thread signal mask
+ * @requires (os.simpleArch == "sparcv9")
+ * @library /testlibrary
+ * @compile Prog.java
+ * @run main/native ThreadSignalMask
+ */
+public class ThreadSignalMask {
+
+    public static void main(String args[]) throws Exception {
+
+        String testClasses = getSystemProperty("test.classes");
+
+        String testNativePath = getSystemProperty("test.nativepath");
+
+        String testJdk = getSystemProperty("test.jdk");
+
+        Path currentDirPath = Paths.get(".");
+
+        Path classFilePath = Paths.get(testClasses,
+                Prog.class.getSimpleName() + ".class");
+
+        // copy Prog.class file to be invoked from native
+        Files.copy(classFilePath,
+                currentDirPath.resolve(Prog.class.getSimpleName() + ".class"),
+                StandardCopyOption.REPLACE_EXISTING);
+
+        Path executableFilePath = Paths.get(testNativePath,
+                ThreadSignalMask.class.getSimpleName());
+
+        Path executableFileLocalPath = currentDirPath.resolve(
+                ThreadSignalMask.class.getSimpleName());
+
+        // copy compiled native executable ThreadSignalMask
+        Files.copy(executableFilePath,
+                executableFileLocalPath,
+                StandardCopyOption.REPLACE_EXISTING);
+
+        executableFileLocalPath.toFile().setExecutable(true);
+
+        long[] intervalsArray = {2000, 5000, 10000, 20000};
+
+        List<String> processArgs = Arrays.asList(
+                executableFileLocalPath.toString(),
+                testJdk);
+        ProcessBuilder pb = new ProcessBuilder(processArgs);
+        pb.redirectOutput(Redirect.INHERIT);
+        pb.redirectError(Redirect.INHERIT);
+        int result = 0;
+        for (long interval : intervalsArray) {
+            Process p = pb.start();
+
+            // sleep for a specified period of time to let native run
+            sleep(interval);
+            p.destroy();
+
+            // wait for process to finish, get exit value and validate it
+            result = p.waitFor();
+            System.out.println("Result = " + result);
+            if (result == 0) {
+                break;
+            }
+        }
+
+        Asserts.assertEquals(result, 0);
+    }
+
+    // Utility method to handle Thread.sleep
+    private static void sleep(long millis) throws InterruptedException {
+        System.out.println("Sleep for " + millis);
+        Thread.sleep(millis);
+    }
+
+    // Utility method to retrieve and validate system properties
+    private static String getSystemProperty(String propertyName) throws Error {
+        String systemProperty = System.getProperty(propertyName, "").trim();
+        System.out.println(propertyName + " = " + systemProperty);
+        if (systemProperty.isEmpty()) {
+            throw new Error("TESTBUG: property " + propertyName + " is empty");
+        }
+        return systemProperty;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ThreadSignalMask/exeThreadSignalMask.c	Mon Nov 23 14:38:20 2015 -0500
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#define _POSIX_PTHREAD_SEMANTICS // to enable POSIX semantics for certain common APIs
+
+#include <jni.h>
+#include <dlfcn.h>
+#include <limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+void *handle;
+char *error;
+char path[PATH_MAX];
+
+jint(JNICALL *jni_create_java_vm)(JavaVM **, JNIEnv **, void *) = NULL;
+
+JavaVM *jvm;
+
+// method to perform dlclose on an open dynamic library handle
+void closeHandle() {
+  dlclose(handle);
+  if ((error = dlerror()) != NULL) {
+    fputs("Error occurred while closing handle\n", stderr);
+  }
+}
+
+// method to exit with a fail status
+void fail() {
+  if (handle) {
+    closeHandle();
+  }
+  exit(1);
+}
+
+// method to handle occurred error and fail
+void handleError(char *messageTitle, char *messageBody) {
+  fprintf(stderr, "%s: %s\n", messageTitle, messageBody);
+  fail();
+}
+
+// method to load the dynamic library libjvm
+void loadJVM() {
+  char lib[PATH_MAX];
+  snprintf(lib, sizeof (lib), "%s/lib/sparcv9/server/libjvm.so", path);
+  handle = dlopen(lib, RTLD_LAZY);
+  if (!handle) {
+    handleError(dlerror(), "2");
+  }
+  fputs("Will load JVM...\n", stdout);
+
+  // find the address of function
+  *(void **) (&jni_create_java_vm) = dlsym(handle, "JNI_CreateJavaVM");
+  if ((error = dlerror()) != NULL) {
+    handleError(error, "3");
+  }
+
+  fputs("JVM loaded okay.\n", stdout);
+}
+
+// method to get created jvm environment
+JNIEnv* initJVM() {
+  JNIEnv *env = NULL;
+  JavaVMInitArgs vm_args;
+  JavaVMOption options[1];
+  jint res;
+
+  options[0].optionString = "-Xrs";
+
+  vm_args.version = JNI_VERSION_1_2;
+  vm_args.nOptions = 1;
+  vm_args.options = options;
+  vm_args.ignoreUnrecognized = JNI_FALSE;
+
+  fputs("Will create JVM...\n", stdout);
+
+  res = (*jni_create_java_vm)(&jvm, &env, &vm_args);
+  if (res < 0) {
+    handleError("Can't create Java VM", strerror(res));
+  }
+
+  fputs("JVM created OK!\n", stdout);
+  return env;
+}
+
+// method to invoke java method from java class
+void callJava(JNIEnv *env) {
+  jclass cls;
+  jmethodID mid;
+  jstring jstr;
+  jobjectArray args;
+
+  cls = (*env)->FindClass(env, "Prog");
+  if (cls == 0) {
+    handleError("FindClass", "Can't find Prog class");
+  }
+
+  mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
+  if (mid == 0) {
+    handleError("GetStaticMethodID", "Can't find Prog.main");
+  }
+
+  jstr = (*env)->NewStringUTF(env, "from C!");
+  if (jstr == 0) {
+    handleError("NewStringUTF", "Out of memory");
+  }
+  args = (*env)->NewObjectArray(env, 1,
+          (*env)->FindClass(env, "java/lang/String"), jstr);
+  if (args == 0) {
+    handleError("NewObjectArray", "Out of memory");
+  }
+  (*env)->CallStaticVoidMethod(env, cls, mid, args);
+
+}
+
+// method to load, init jvm and then invoke java method
+void* loadAndCallJava(void* x) {
+  JNIEnv *env;
+
+  fputs("Some thread will create JVM.\n", stdout);
+  loadJVM();
+  env = initJVM();
+
+  fputs("Some thread will call Java.\n", stdout);
+
+  callJava(env);
+
+  if ((*jvm)->DetachCurrentThread(jvm) != 0)
+    fputs("Error: thread not detached!\n", stderr);
+  fputs("Some thread exiting.\n", stdout);
+  return env;
+}
+
+int main(int argc, char **argv) {
+  JNIEnv *env;
+  sigset_t set;
+  pthread_t thr1;
+  pthread_attr_t attr;
+  size_t ss = 0;
+  int sig;
+  int rc; // return code for pthread_* methods
+
+  // verify input
+  if (argc != 2) {
+    handleError("usage", "a.out jdk_path");
+  }
+  // copy input jdk path into a char buffer
+  strncpy(path, argv[1], PATH_MAX);
+  // add null termination character
+  path[PATH_MAX - 1] = '\0';
+
+  fputs("Main thread will set signal mask.\n", stdout);
+
+  // initialize the signal set
+  sigemptyset(&set);
+  // add a number of signals to a signal set
+  sigaddset(&set, SIGPIPE);
+  sigaddset(&set, SIGTERM);
+  sigaddset(&set, SIGHUP);
+  sigaddset(&set, SIGINT);
+
+  // examine and change mask of blocked signal
+  if ((rc = pthread_sigmask(SIG_BLOCK, &set, NULL))) {
+    // handle error if occurred
+    handleError("main: pthread_sigmask() error", strerror(rc));
+  }
+
+  // initializes the thread attributes object with default attribute values
+  if ((rc = pthread_attr_init(&attr))) {
+    // handle error if occurred
+    handleError("main: pthread_attr_init() error", strerror(rc));
+  }
+
+  ss = 1024 * 1024;
+  // set the stack size attribute of the thread attributes object
+  if ((rc = pthread_attr_setstacksize(&attr, ss))) {
+    // handle error if occurred
+    handleError("main: pthread_attr_setstacksize() error", strerror(rc));
+  }
+  // get the stack size attribute of the thread attributes object
+  if ((rc = pthread_attr_getstacksize(&attr, &ss))) {
+    // handle error if occurred
+    handleError("main: pthread_attr_getstacksize() error", strerror(rc));
+  }
+  fprintf(stderr, "Stack size: %zu\n", ss);
+
+  // start a new thread in the calling process,
+  // loadAndCallJava logic is passed as a start_routine argument
+  if ((rc = pthread_create(&thr1, NULL, loadAndCallJava, NULL))) {
+    // handle error if occurred
+    handleError("main: pthread_create() error", strerror(rc));
+  }
+
+  // initialize the signal set
+  sigemptyset(&set);
+  // add a number of signals to a signal set
+  sigaddset(&set, SIGTERM);
+  sigaddset(&set, SIGHUP);
+  sigaddset(&set, SIGINT);
+
+  fputs("Main thread waiting for signal.\n", stdout);
+
+  do {
+    int err;
+
+    sig = 0;
+    err = sigwait(&set, &sig);
+    if (err != 0) {
+      // print error message if unexpected signal occurred
+      fprintf(stderr, "main: sigwait() error:  %s\n", strerror(err));
+    } else {
+      // print success message and exit if expected signal occurred
+      // this branch generally acts when JVM executes destroy()
+      fprintf(stdout, "main: sigwait() got:  %d\nSucceed!\n", sig);
+      exit(0);
+    }
+  } while (sig != SIGTERM && sig != SIGINT); // exit the loop condition
+
+  // join with a terminated thread
+  if ((rc = pthread_join(thr1, NULL))) {
+    // handle error if occurred
+    handleError("main: pthread_join() error", strerror(rc));
+  }
+
+  // close an open dynamic library handle
+  closeHandle();
+  fputs("Main thread exiting.\n", stdout);
+  return 0;
+}