JDK-8190375 : Java Crash in JavaBug.formatPos(I)Ljava/lang/String
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9,9.0.1,10
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: x86_64
  • Submitted: 2017-10-30
  • Updated: 2018-03-01
  • Resolved: 2017-11-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 10
10 b34Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)


FULL OS VERSION :
Linux N042 4.10.0-37-generic #41~16.04.1-Ubuntu SMP Fri Oct 6 22:42:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fe05160fd22, pid=1101, tid=1102
#
# JRE version: Java(TM) SE Runtime Environment (9.0+11) (build 9.0.1+11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (9.0.1+11, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# J 210 c2 JavaBug.formatPos(I)Ljava/lang/String; (97 bytes) @ 0x00007fe05160fd22 [0x00007fe05160fca0+0x0000000000000082]
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %P" (or dumping to /home/mbu/tmp/JavaBug/core.1101)
#
# An error report file with more information is saved as:
# /home/mbu/tmp/JavaBug/hs_err_pid1101.log
Could not load hsdis-amd64.so; library not loadable; PrintAssembly is disabled
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#


THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try

REGRESSION.  Last worked in version 8u152

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the demo code and run it.
The JCM crashes after about 2500 iterations. Sometimes earlier, sometimes later.

EXPECTED VERSUS ACTUAL BEHAVIOR :
No SIGSEGV
REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class JavaBug {
  public static void main(String[] args) {
    for (int i = 0; i < 1000000; i++) {
      System.out.println(i);
      String foo = formatPos(i);
      }
    }

    private static String formatPos( int p )
    {
      boolean negative = p < 0;
      if ( negative )
        p = -p;
      char[] ac = new char[12];
      int i = 11;
      while (p != 0 || i > 3)
      {
        ac[i--] = (char) ( '0' + ( p % 10 ) );
        p /= 10;
        if ( i == 5 )
          ac[i--] = '.';
      }
      if ( negative )
        ac[i--] = '-';
      return new String( ac, i + 1, 11 - i );
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Java 8


Comments
The problem is that PhiNode::Value sets the type of the counted loop tripcount Phi to int:4..11 and as a result the i <= 3 check is removed: 122 ConI === 0 [[ 123 206 ]] #int:3 110 Phi === 287 279 283 [[ 220 283 227 183 123 168 141 167 ]] #int:4..11:www #tripcount !jvms: JavaBug::formatPos @ bci:25 123 CmpI === _ 110 122 [[]] !jvms: JavaBug::formatPos @ bci:31 124 Bool === _ 123 [[ 125 ]] [le] !jvms: JavaBug::formatPos @ bci:31 The loop runs out of its lower bounds and we crash with an invalid array access. [~roland], you implemented this optimization with JDK-8145322. Could you please have a look?
31-10-2017

The problem was introduced by JDK-8145322. Reverting the cfgnode.cpp change fixes the issue: diff -r a0ebc3ac4e54 src/hotspot/share/opto/cfgnode.cpp --- a/src/hotspot/share/opto/cfgnode.cpp Wed Oct 25 13:43:14 2017 +0200 +++ b/src/hotspot/share/opto/cfgnode.cpp Tue Oct 31 08:50:35 2017 +0100 @@ -906,35 +906,25 @@ return Type::TOP; // Check for trip-counted loop. If so, be smarter. - CountedLoopNode* l = r->is_CountedLoop() ? r->as_CountedLoop() : NULL; - if (l && ((const Node*)l->phi() == this)) { // Trip counted loop! + CountedLoopNode *l = r->is_CountedLoop() ? r->as_CountedLoop() : NULL; + if( l && l->can_be_counted_loop(phase) && + ((const Node*)l->phi() == this) ) { // Trip counted loop! // protect against init_trip() or limit() returning NULL - if (l->can_be_counted_loop(phase)) { - const Node *init = l->init_trip(); - const Node *limit = l->limit(); - const Node* stride = l->stride(); - if (init != NULL && limit != NULL && stride != NULL) { - const TypeInt* lo = phase->type(init)->isa_int(); - const TypeInt* hi = phase->type(limit)->isa_int(); - const TypeInt* stride_t = phase->type(stride)->isa_int(); - if (lo != NULL && hi != NULL && stride_t != NULL) { // Dying loops might have TOP here - assert(stride_t->_hi >= stride_t->_lo, "bad stride type"); - if (stride_t->_hi < 0) { // Down-counter loop - swap(lo, hi); - return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3); - } else if (stride_t->_lo >= 0) { - return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3); - } + const Node *init = l->init_trip(); + const Node *limit = l->limit(); + if( init != NULL && limit != NULL && l->stride_is_con() ) { + const TypeInt *lo = init ->bottom_type()->isa_int(); + const TypeInt *hi = limit->bottom_type()->isa_int(); + if( lo && hi ) { // Dying loops might have TOP here + int stride = l->stride_con(); + if( stride < 0 ) { // Down-counter loop + const TypeInt *tmp = lo; lo = hi; hi = tmp; + stride = -stride; + const Node* stride = l->stride(); } + if( lo->_hi < hi->_lo ) // Reversed endpoints are well defined :-( + return TypeInt::make(lo->_lo,hi->_hi,3); } - } else if (l->in(LoopNode::LoopBackControl) != NULL && - in(LoopNode::EntryControl) != NULL && - phase->type(l->in(LoopNode::LoopBackControl)) == Type::TOP) { - // During CCP, if we saturate the type of a counted loop's Phi - // before the special code for counted loop above has a chance - // to run (that is as long as the type of the backedge's control - // is top), we might end up with non monotonic types - return phase->type(in(LoopNode::EntryControl)); } }
31-10-2017

We crash in C2 compiler code at: 0x00007f5bfd15d845: mov %bp,0x10(%rax,%rcx,2) ;*castore {reexecute=0 rethrow=0 return_oop=0} ; - JavaBug::formatPos@47 (line 18) RAX=0x00000006d29f1e88 is an oop [C {0x00000006d29f1e88} - klass: {type array char} - length: 12 - 0: 30 0 - 1: 30 0 - 2: 30 0 - 3: 30 0 - 4: 30 0 - 5: 2e . - 6: 30 0 - 7: 30 0 - 8: 31 1 - 9: 33 3 - 10: 36 6 - 11: 37 7 RCX=0x00000000ffffffff RCX is an invalid array index. ILW = Crash in C2 compiled code due to invalid array index (regression), single test but easy to reproduce, disable compilation = HMM = P2
31-10-2017

This is an regression stated from 9 ea b105. Below are the results to confirm on that. 8u152 - Pass 9 ea b104 - Pass 9 ea b105 - Fail //regression started from here 9 GA - Fail 9.0.1 GA - Fail 10 ea b26 - Fail Coupe of other tests performed -Xint - Pass XX:TieredStopAtLevel=1 = Pass
30-10-2017