JDK-6817995 : G1: Error: guarantee(!r->is_young(),"It was evicted in the current minor cycle.")
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: hs15
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2009-03-16
  • Updated: 2010-04-04
  • Resolved: 2009-09-14
Related Reports
Duplicate :  
Relates :  
Description
One of Igor's JPRT submissions hit this assertion failure:

[GC pause (young) 183M->87M(221M), 0.1608904 secs]
[GC pause (young) 185M->91M(221M), 0.2777634 secs]
[GC pause (young) 181M->97M(221M), 0.1786966 secs]
[GC pause (young) 183M->102M(221M), 0.1913175 secs]
[GC pause (young) 181M->108M(221M), 0.1928595 secs]
[GC pause (young) 180M->114M(221M), 0.1890257 secs]
[GC pause (young) 181M->120M(221M), 0.1939025 secs]
[GC pause (young) 181M->127M(221M), 0.1923573 secs]
[GC pause (young) 181M->133M(221M), 0.1976771 secs]
[GC pause (young) (initial-mark)[GC concurrent-mark-start]
181M->139M(221M), 0.2008953 secs]
[GC concurrent-mark-end, 0.3158352 sec]
[GC remark, 0.0072940 secs]
[GC concurrent-count-start]
[GC concurrent-count-end, 0.3820240]
[GC cleanup 161M->125M(221M), 0.0106024 secs]
[GC concurrent-cleanup-start]
[GC concurrent-cleanup-end, 0.0075199]
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (g1RemSet.cpp:887), pid=25527, tid=23
#  Error: guarantee(!r->is_young(),"It was evicted in the current minor cycle.")
#
# JRE version: 7.0-b50
# Java VM: OpenJDK Server VM (15.0-b02-2009-03-16-074947.iv159533.hotspot-gc mixed mode solaris-sparc )
# An error report file with more information is saved as:
# /opt/jprt/products/T3/jbb/hs_err_pid25527.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#
Abort - core dumped

We've only seen this once (so far at least), despite a few more JPRT submissions since.

Comments
EVALUATION John Cuthbertson fixed this with a workaround as part of 6819077.
14-09-2009

EVALUATION So, here's a possible, but also quite improbable, explanation of how this can happen. As we discussed with Igor, when a particular card is processed, if it's found to be young, then it's discarded and not processed further (i.e., added to the cache). So, how is it possible for a card to be found to be young in the cache? On potential explanation is that the card was not young when added to the cache, but it became young a bit later. Here's a possible scenario on how this can happen: We have a region, say, R that has one object, say, X. X is still live when the marking cycle starts. A bit after the marking cycle starts, X is updated (a card C that's on R is enqueued) and shortly after it that becomes unreachable, before the marking cycle visits it. During cleanup, X is of course dead and also it so happens that R is totally empty (see later for a bit more on this). So, cleanup reclaims R and puts it on the free list. Later, R is re-allocated as a young region and then we come across card C in the cache that now looks to be young. Bingo. So, how likely is that X being updated during the marking cycle and then R is found to be totally empty by the time cleanup happens? Very unlikely. But, it could that X is say the last live object on R, or X is humongous (i.e. it's the only object on R). The GC log from the failure kind of supports the above, given that there are not evacuation pauses between the marking cycle starting and the failure happening, which means that update buffers / cache were not processed in their entirety. Another more sinister explanation is that X is not dead and/or R is not really totally empty, but marking reclaims them due to a mistake. Let's hope this is not the case!
16-03-2009