United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7048782 CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
JDK-7048782 : CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359

Details
Type:
Bug
Submit Date:
2011-05-26
Status:
Closed
Updated Date:
2011-11-25
Project Name:
JDK
Resolved Date:
2011-09-30
Component:
hotspot
OS:
generic
Sub-Component:
gc
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:
hs22 (b01)

Related Reports
Backport:
Backport:
Relates:

Sub Tasks

Description
gc/gctests/LargeObjects/large005
http://sqeweb.sfbay.sun.com/nfs/results/vm/gtee/JDK7/NIGHTLY/VM/2011-05-25/GC_Baseline-Xconc/vm/solaris-amd64/server/mixed/solaris-amd64_vm_server_mixed_vm.gc.testlist/ResultDir/large005/hs_err_pid23650.log



;; Using jvm: "/export/local/common/jdk/baseline/solaris-amd64/jre/lib/amd64/server/libjvm.so"
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/tmp/jprt/P1/B/235027.ysr/source/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp:359), pid=23650, tid=4
#  assert(last_chunk_index_to_check<= last_chunk_index) failed: Out of bounds: last_chunk_index_to_check 0x0000000000000193 exceeds last_chunk_index 0x0000000000000192
#
# JRE version: 7.0-b143
# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.0-b14-internal-201105232350.ysr.botloop-fastdebug mixed mode solaris-amd64 )
# Core dump written. Default location: /export/local/51065.JDK7.NIGHTLY.VM+solaris-amd64_vm_server_mixed_vm.gc.testlist/results/ResultDir/large005/core or core.23650
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x0000000000467800):  GCTaskThread [stack: 0x0000000000000000,0x0000000000000000] [id=4]

Stack: 
[error occurred during error reporting (printing stack bounds), id 0xe0000000]

Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x2601ff2]  void VMError::report(outputStream*)+0x8c6;;  void VMError::report(outputStream*)+0x8c6
V  [libjvm.so+0x2603131]  void VMError::report_and_die()+0x4fd;;  void VMError::report_and_die()+0x4fd
V  [libjvm.so+0xe45a27]  void report_vm_error(const char*,int,const char*,const char*)+0x55f;;  void report_vm_error(const char*,int,const char*,const char*)+0x55f
V  [libjvm.so+0x2602b3b]  void VMError::report(outputStream*)+0x140f;;  void VMError::report(outputStream*)+0x140f
V  [libjvm.so+0x2603131]  void VMError::report_and_die()+0x4fd;;  void VMError::report_and_die()+0x4fd
V  [libjvm.so+0xe45a27]  void report_vm_error(const char*,int,const char*,const char*)+0x55f;;  void report_vm_error(const char*,int,const char*,const char*)+0x55f
V  [libjvm.so+0x208bf16]  void CardTableModRefBS::process_chunk_boundaries(Space*,DirtyCardToOopClosure*,MemRegion,MemRegion,signed char**,unsigned long,unsigned long)+0x113a;;  void CardTableModRefBS::process_chunk_boundaries(Space*,DirtyCardToOopClosure*,MemRegion,MemRegion,signed char**,unsigned long,unsigned long)+0x113a
V  [libjvm.so+0x2089beb]  void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space*,MemRegion,OopsInGenClosure*,CardTableRS*,int)+0x98f;;  void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space*,MemRegion,OopsInGenClosure*,CardTableRS*,int)+0x98f
V  [libjvm.so+0xa72307]  void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space*,MemRegion,OopsInGenClosure*,CardTableRS*)+0x93;;  void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space*,MemRegion,OopsInGenClosure*,CardTableRS*)+0x93
V  [libjvm.so+0xa78492]  void CardTableRS::younger_refs_in_space_iterate(Space*,OopsInGenClosure*)+0x212;;  void CardTableRS::younger_refs_in_space_iterate(Space*,OopsInGenClosure*)+0x212
V  [libjvm.so+0xd5320a]  void ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure*)+0x5e;;  void ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure*)+0x5e
V  [libjvm.so+0x108b636]  void GenCollectedHeap::gen_process_strong_roots(int,bool,bool,bool,SharedHeap::ScanningOption,OopsInGenClosure*,bool,OopsInGenClosure*)+0x416;;  void GenCollectedHeap::gen_process_strong_roots(int,bool,bool,bool,SharedHeap::ScanningOption,OopsInGenClosure*,bool,OopsInGenClosure*)+0x416
V  [libjvm.so+0x20a7466]  void ParNewGenTask::work(int)+0x1ee;;  void ParNewGenTask::work(int)+0x1ee
V  [libjvm.so+0x263afab]  void GangWorker::loop()+0x51f;;  void GangWorker::loop()+0x51f
V  [libjvm.so+0x2052086]  java_start+0x6a6;;  java_start+0x6a6
C  [libc.so.1+0xd72cb]  _thr_setup+0x5b;;  _thr_setup+0x5b
C  [libc.so.1+0xd7500]  ht_pause+0x10;;  _lwp_start+0x0

...

Heap
 par new generation   total 19392K, used 17581K [0xfffffd7fb4800000, 0xfffffd7fb5d00000, 0xfffffd7fbee60000)
  eden space 17280K,  93% used [0xfffffd7fb4800000, 0xfffffd7fb57b2cc0, 0xfffffd7fb58e0000)
  from space 2112K,  71% used [0xfffffd7fb5af0000, 0xfffffd7fb5c68a00, 0xfffffd7fb5d00000)
  to   space 2112K,   0% used [0xfffffd7fb58e0000, 0xfffffd7fb58e0000, 0xfffffd7fb5af0000)
 concurrent mark-sweep generation total 68580K, used 68328K [0xfffffd7fbee60000, 0xfffffd7fc3159000, 0xfffffd7ff3800000)
 concurrent-mark-sweep perm gen total 21248K, used 4557K [0xfffffd7ff3800000, 0xfffffd7ff4cc0000, 0xfffffd7ff8a00000)

...

VM Arguments:
jvm_args: -Xmixed -XX:-PrintVMOptions -Xconcgc -XX:+CMSClassUnloadingEnabled -XX:+StartAttachListener -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseGCOverheadLimit 
java_command: gc.gctests.LargeObjects.large001.large001 -largeClassesPath /export/local/common/testbase/7/vm/vm/bin/newclass -isOverLimitFields true -aggregationDepth 3 -t 1
Launcher Type: SUN_STANDARD

...

OS:                       Solaris 10 10/09 s10x_u8wos_08a X86
           Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
                        Use is subject to license terms.
                           Assembled 16 September 2009

uname:SunOS 5.10 Generic_142901-13 i86pc  (T2 libthread)
rlimit: STACK 10000k, CORE infinity, NOFILE 65536, AS infinity
load average:1.27 1.49 1.71

CPU:total 2 (1 cores per cpu, 1 threads per core) family 15 model 37 stepping 1, cmov, cx8, fxsr, mmx, sse, sse2, sse3, mmxext, 3dnowpref

Memory: 4k page, physical 4127784k(2013980k free)

vm_info: Java HotSpot(TM) 64-Bit Server VM (21.0-b14-internal-201105232350.ysr.botloop-fastdebug) for solaris-amd64 JRE (1.7.0), built on May 23 2011 19:59:20 by "jprtadm" with Sun Studio 12u1

time: Wed May 25 21:59:55 2011
elapsed time: 3 seconds

# Host info: SunOS vm-v20z-5 5.10 Generic_142901-13 i86pc i386 i86pc

                                    

Comments
EVALUATION

The assert is to strong when the heap is expanding and a previously co-terminal free
chunk is coalesced with the expansion delta. Basically at that point the "used"
has changed to a larger value so the old snapshot is not valid, and the last block
can potentially exceed the end of the old snapshot. The assert should be suitably adjusted
to account for this occurrence.
                                     
2011-05-26
SUGGESTED FIX

diff --git a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp
--- a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp
+++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp
@@ -348,15 +348,30 @@
         // cleared before we had a chance to examine it. In that case, the value
         // will have been logged in the LNC for that chunk.
         // We need to examine as many chunks to the right as this object
-        // covers.
-        const uintptr_t last_chunk_index_to_check = addr_to_chunk_index(last_block + last_block_size - 1)
-                                                    - lowest_non_clean_base_chunk_index;
-        DEBUG_ONLY(const uintptr_t last_chunk_index = addr_to_chunk_index(used.last())
-                                                      - lowest_non_clean_base_chunk_index;)
-        assert(last_chunk_index_to_check <= last_chunk_index,
-               err_msg("Out of bounds: last_chunk_index_to_check " INTPTR_FORMAT
-                       " exceeds last_chunk_index " INTPTR_FORMAT,
-                       last_chunk_index_to_check, last_chunk_index));
+        // covers. However, we need to bound this checking to the largest
+        // entry in the LNC array: this is because the heap may expand
+        // after the LNC array has been created but before we reach this point,
+        // and the last block in our chunk may have been expanded to include
+        // the expansion delta (and possibly subsequently allocated from, so
+        // it wouldn't be sufficient to check whether that last block was
+        // or was not an object at this point).
+        uintptr_t last_chunk_index_to_check = addr_to_chunk_index(last_block + last_block_size - 1)
+                                              - lowest_non_clean_base_chunk_index;
+        const uintptr_t last_chunk_index    = addr_to_chunk_index(used.last())
+                                              - lowest_non_clean_base_chunk_index;
+        if (last_chunk_index_to_check > last_chunk_index) {
+          assert(last_block + last_block_size > used.end(),
+                 err_msg("Inconsistency detected: last_block [" PTR_FORMAT "," PTR_FORMAT "]"
+                         " does not exceed used.end() = " PTR_FORMAT ","
+                         " yet last_chunk_index_to_check " PTR_FORMAT " exceeds last_chunk_index " PTR_FORMAT,
+                         last_chunk_index_to_check, last_chunk_index));
+          assert(sp->used_region().end() > used.end(),
+                 err_msg("Expansion did not happen: "
+                         "[" PTR_FORMAT "," PTR_FORMAT ") -> [" PTR_FORMAT "," PTR_FORMAT ")",
+                         sp->used_region().start(), sp->used_region().end(), used.start(), used.end()));
+          NOISY(tty->print_cr(" process_chunk_boundary: heap expanded; explicitly bounding last_chunk");)
+          last_chunk_index_to_check = last_chunk_index;
+        }
         for (uintptr_t lnc_index = cur_chunk_index + 1;
              lnc_index <= last_chunk_index_to_check;
              lnc_index++) {
                                     
2011-05-27
EVALUATION

The above evaluation is not entirely correct. It is true that the assert will
not hold when the heap expands. However, the assert does check a property that
had better hold or else we may end up accessing past the end of the LNC array
and potentially read junk or, worse, segv in the read if that portion is not mapped.
So the largeset chunk index to check should in fact be bounded by the
largest chunk index that the assert was checking against.

Thus, this affects not only debug code but also product code. See suggested fix for the
delta under test and (which will be submitted for) review.
                                     
2011-05-27
WORK AROUND

The bug can be worked around by setting -Xmx == -Xms *and* -XX:PermSize == -XXMaxPermSize.
                                     
2011-05-27
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-gc/hotspot/rev/5c0a3c1858b1
                                     
2011-06-08
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-comp/hotspot/rev/5c0a3c1858b1
                                     
2011-07-08
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-rt/hotspot/rev/5c0a3c1858b1
                                     
2011-07-08



Hardware and Software, Engineered to Work Together