United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4957832 JVM Server Crash on Solaris
JDK-4957832 : JVM Server Crash on Solaris

Details
Type:
Bug
Submit Date:
2003-11-21
Status:
Closed
Updated Date:
2004-04-30
Project Name:
JDK
Resolved Date:
2003-12-16
Component:
hotspot
OS:
solaris_2.6
Sub-Component:
compiler
CPU:
generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
5.0
Fixed Versions:
1.4.2_05 (05)

Related Reports
Backport:

Sub Tasks

Description
The Server VM crashes on solaris running the test case below with the following core dump (tested in the latest 1.5 build 28):

#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  Internal Error (4E4D4554484F440E43505004F6 01), pid=25960, tid=1
#
# Java VM: Java HotSpot(TM) Server VM (1.5.0-beta-b28 mixed mode)

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

Current thread (0x00036ee0):  JavaThread "main" [_thread_in_Java, id=1]

Stack: [0xffb80000,0xffc00000),  sp=0xffbfda78,  free space=502k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x5e6414]
V  [libjvm.so+0x3c5478]
V  [libjvm.so+0x55b210]
V  [libjvm.so+0x29cadc]
V  [libjvm.so+0x25be10]
C  [libthread.so.1+0x160a8]
C  [libthread.so.1+0xfde0]
C  [libthread.so.1+0xff90]
J  test1.check([Ljava/lang/String;[Ljava/lang/String;)[[I
v  ~I2CAdapter
j  test1.main([Ljava/lang/String;)V+230
v  ~StubRoutines::call_stub
V  [libjvm.so+0x165cf8]
V  [libjvm.so+0x282da4]
C  [java+0x295c]  main+0x10f0


---------------  P R O C E S S  ---------------

Java Threads: ( => current thread )
  0x0014bbe8 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=9]
  0x0014ac68 JavaThread "CompilerThread1" daemon [_thread_blocked, id=8]
  0x00149e98 JavaThread "CompilerThread0" daemon [_thread_blocked, id=7]
  0x00148ac0 JavaThread "AdapterThread" daemon [_thread_blocked, id=6]
  0x00147db8 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=5]
  0x0013dde0 JavaThread "Finalizer" daemon [_thread_blocked, id=4]
  0x0013da28 JavaThread "Reference Handler" daemon [_thread_blocked, id=3]
=>0x00036ee0 JavaThread "main" [_thread_in_Java, id=1]

Other Threads:
  0x0013bb38 VMThread [id=2]
  0x0014c830 WatcherThread [id=10]

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

Heap
 def new generation   total 2112K, used 1322K [0xef400000, 0xef620000, 0xf0950000)
  eden space 2048K,  61% used [0xef400000, 0xef53a928, 0xef600000)
  from space 64K, 100% used [0xef610000, 0xef620000, 0xef620000)
  to   space 64K,   0% used [0xef600000, 0xef600000, 0xef610000)
 tenured generation   total 1408K, used 27K [0xf0950000, 0xf0ab0000, 0xf3400000)
   the space 1408K,   1% used [0xf0950000, 0xf0956c28, 0xf0956e00, 0xf0ab0000)
 compacting perm gen  total 16384K, used 1331K [0xf3400000, 0xf4400000, 0xf8c00000)
   the space 16384K,   8% used [0xf3400000, 0xf354ceb8, 0xf354d000, 0xf4400000)
No shared spaces configured.

Dynamic libraries:
0x00010000 	/java/re/jdk/1.5/latest/binaries/solaris-sparc/bin/java
0xff370000 	/usr/lib/libthread.so.1
0xff3a0000 	/usr/lib/libdl.so.1
0xff280000 	/usr/lib/libc.so.1
0xff350000 	/usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1
0xfe800000 	/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc/server/libjvm.so
0xff250000 	/usr/lib/libsocket.so.1
0xff230000 	/usr/lib/libsched.so.1
0xff1f0000 	/usr/lib/libCrun.so.1
0xff1c0000 	/usr/lib/libm.so.1
0xff100000 	/usr/lib/libnsl.so.1
0xff360000 	/usr/lib/libw.so.1
0xff0d0000 	/usr/lib/libmp.so.2
0xff0b0000 	/usr/lib/librt.so.1
0xff090000 	/usr/lib/libaio.so.1
0xff060000 	/usr/lib/libmd5.so.1
0xff040000 	/usr/platform/SUNW,Ultra-5_10/lib/libmd5_psr.so.1
0xff000000 	/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc/native_threads/libhpi.so
0xfefb0000 	/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc/libverify.so
0xfef60000 	/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc/libjava.so
0xfef40000 	/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc/libzip.so

VM Arguments:
java_command: test1

Environment Variables:
JAVA_HOME=/export/jdk1.4.2_01
PATH=/home/sko/bin:/usr/openwin/bin:/usr/dt/bin:/usr/bin:/usr/sbin:/sbin:/usr/ucb:/usr/dist/local/exe:/usr/dist/exe:/usr/lib/lp/postscript:.
LD_LIBRARY_PATH=/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc/server:/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/lib/sparc:/net/koori.sfbay/p/jdk08/jdk/1.5.0/beta/b28/binaries/solaris-sparc/jre/../lib/sparc:/home/sko/xemacs/local/lib/:/usr/openwin/lib:/usr/dt/lib:/usr/lib
SHELL=/bin/csh
DISPLAY=d-usca22-163-78:0.0
HOSTTYPE=sparc
OSTYPE=solaris2.5.1
MACHTYPE=sparc-sun-solaris2.5.1


---------------  S Y S T E M  ---------------

OS:                        Solaris 9 12/02 s9s_u2wos_10 SPARC
           Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
                        Use is subject to license terms.
                           Assembled 05 November 2002

uname:SunOS 5.9 Generic_112233-04 sun4u  (T2 libthread)
rlimit: STACK 8192k, CORE infinity, NOFILE 65536, AS infinity
load average:1.29 1.14 1.09

CPU:total 1(active 1) has_v8, has_v9, has_vis1

Memory: 8k page, physical 262144k(16376k free)

vm_info: Java HotSpot(TM) Server VM (1.5.0-beta-b28) for solaris-sparc, built on Nov 12 2003 02:12:04 by unknown with unknown Workshop:0x550

Test Case:
==========

run: java -server test1

import java.io.*;
import java.util.*;
import java.lang.*;
public class test1 implements Serializable
{
  
  private static final String[] SENNIN_IPPAN_GYOUSHU = { "1", "4", "7" };
  private static final String[] SENNIN_TOKUTEI_7_GYOUSHU = { "3", "9" };
  private static final String[] SENNIN_TOKUTEI_IGAI_GYOUSHU = { "2", "5",
"6", "8", "9" };
  private static final String[] KOKKAN_TOKUTEI_7_GYOUSHU = { "3" };
  private static final String[] KOKKAN_TOKUTEI_IGAI_GYOUSHU = { "2", "5",
"6", "8" };
  
  private static final int TOKUTEI_GYOUSHU_DO = ( 1 - 1 );
  private static final int TOKUTEI_GYOUSHU_KEN = ( 2 - 1 );
  private static final int TOKUTEI_GYOUSHU_DEN = ( 8 - 1 );
  private static final int TOKUTEI_GYOUSHU_KAN = ( 9 - 1 );
  private static final int TOKUTEI_GYOUSHU_KOU = ( 11 - 1 );
  private static final int TOKUTEI_GYOUSHU_HO = ( 13 - 1 );
  private static final int TOKUTEI_GYOUSHU_ZOU = ( 23 - 1 );


public static int[][] check(   String[] p_GyoushuEng , String[] test9_str) 
  {
    
    int[][] i_result = new int[5][ p_GyoushuEng.length ];
    int[] count = new int[28];
    String[][] s_Gyoushu = new String[16][28];
    String[] tokuteiTemp = new String[28];
    for( int i = 0; i < i_result.length; i++ ){
      for( int j = 0; j < i_result[i].length; j++){
        i_result[i][j] = 10;
      }
    }
    
    for( int i = 0; i < count.length; i++ ){
      count[i] = 0;
    }
    
    
    
   //set up s_Gyoush in some fashion here
    int k = 0;
    for( int i = 0; i < test9_str.length; i++ ){
      if( !test9_str[i].equals("") && !test9_str[i].equals(" ") ){
        if( ( foo( test9_str[i] ) ) == null ){
          i_result[2][i] = 32;
          s_Gyoushu[k] = null;
	  System.err.println ("s[" + k + "] is null");
          k++;
          s_Gyoushu[k] = null;
	  System.err.println ("s[" + k + "] is null");
          k++;
        }
        else{
          s_Gyoushu[k] = foo( test9_str[i] );
	  System.err.println ("s[" + k + "] is foo");
          k++;
          s_Gyoushu[k] = foo( test9_str[i] );
	  System.err.println ("s[" + k + "] is foo");
          k++;
        }
      }
      System.err.println("k " + k);
    
    if( p_GyoushuEng.length == 28 ){
      for( int j = 0; j < p_GyoushuEng.length; j++ ){
        if( !p_GyoushuEng[j].equals("") &&
	    !p_GyoushuEng[j].equals(" ") &&
	    !p_GyoushuEng[j].equals("0")){

          for( int z = 0; z < s_Gyoushu.length; z++ ){
	    System.err.println ("> z " + z + " j " + j);
            if( s_Gyoushu[z] != null ){
	      System.err.println ("< z " + z + " j " + j);
              //System.err.println(z);  
              //System.err.println(j);  
              if( p_GyoushuEng[j].equals( s_Gyoushu[z][j] ) ){
                count[j]++;
              }
            }
          }
        }
        else{
          count[j] = -1;
        }
      }
      for ( int z = 0; z < count.length; z++ ){
        if( count[z] == 0 ){
          i_result[3][z] = 26;
        }
      }
    }
    else{
      for( int z = 0; z < i_result[1].length; z++){
        i_result[1][z] = 28;
      }
    }
    
  }
    return i_result;
 }  

  public static String[] foo(String s1)
  {
    String[] temp1={};
    String[] temp2={"", "san", "", "san", "", "", "", "",
                    "", "", "", "", "", "", "", "", "",   
                    "", "", "", "", "", "", "", "", "", "", ""   
                    };
    if(s1.equals("san"))
     return null;
    else
      return temp2;
  }
  public static void main(String[] args)
  {
     int[][] result = new int[5][28];
     String[] test9_str1 = { "san", "san", "sandy", "so", "sarayu",
"saravan", "sar"};
     String[] p_Gyou = {"", "",  "uma", "um", "um2", "ush", "usha", "viji",
"",
                         "", "", "","", "", "", 
                         "", "", "","", "", "", "saro1",
                         "", "", "","", "sandy2","" };
   for(int i =0; i < 100; i++){     
    result = check(p_Gyou, test9_str1 );
    if(i % 6 == 0){
     for(int k=0; k < 5; k++)
       for(int j=0; j< 28; j++) {
         System.err.print(" " + result[k][j]);
      }
      System.err.println ("");
    } 
   }
  }
};

-----

Two smaller test cases are attached.

###@###.### 2003-12-05

                                    

Comments
EVALUATION

At potential (and real) array assignment sites, the server compiler is failing to weaken the type information it knows about multidimensional arrays.  For example, in the given test program, the array s_Gyoushu is known to have type String [16][28] at allocation time.

After the assignment s_Gyoushu[k] = null, we can only know that the type of s_Gyoushu is String[16][].  The server compiler fails to update its internal type representation for s_Gyoushu.

The compiler then generates bad code (really, no code) for the if( s_Gyoushu[z] != null) check, because is "knows" that s_Gyoushu[k] is non-null with length 28.
The user's program unexpected SEGV's because of this bad decision.

This bug seems to date back at least to the 1.3.1 release.

###@###.### 2003-11-25
                                     
2003-11-25
WORK AROUND

--- parse3.cpp	Tue Nov 25 09:40:35 2003
***************
*** 373,384 ****
  
    // Fill in the dimensions with known sizes (passed in the JVM stack)
    for (int i = 0; i < ndimensions; i++) {
!     Node* count_val = length[i];
!     // try to get a better type than POS for the size
!     const Type* count_type = count_val->bottom_type()->join(TypeInt::POS);
      assert(count_type->is_int(), "must be integer");
      const TypeAry* arr0 = TypeAry::make(prev_type, (TypeInt*)count_type);
!     prev_type = TypeAryPtr::make(TypePtr::NotNull, arr0, prev_array, true, 0);
      prev_array = NULL; // array klasses can be lazy, except the first
    }
    const TypeAryPtr* arr = (const TypeAryPtr*)prev_type;
--- 373,388 ----
  
    // Fill in the dimensions with known sizes (passed in the JVM stack)
    for (int i = 0; i < ndimensions; i++) {
!     const Type* count_type = TypeInt::POS;
!     TypePtr::PTR ptr = TypePtr::BotPTR;
!     if (i == ndimensions - 1) {
!       // try to get a better type than POS for the size
!       count_type = length[i]->bottom_type()->join(count_type);
!       ptr = TypePtr::NotNull;
!     } 
      assert(count_type->is_int(), "must be integer");
      const TypeAry* arr0 = TypeAry::make(prev_type, (TypeInt*)count_type);
!     prev_type = TypeAryPtr::make(ptr, arr0, prev_array, true, 0);
      prev_array = NULL; // array klasses can be lazy, except the first
    }
    const TypeAryPtr* arr = (const TypeAryPtr*)prev_type;

###@###.### 2003-11-25
                                     
2003-11-25
SUGGESTED FIX

We can either (1) be less exact in our type info at multi-dimensional arrays allocations or (2) update the array type information for values in our map at aastore and call sites.

Option #2 is more involved, but more likely to retain any performance wins.
Option #1 is simpler but riskier, performance-wise.  A prototype for option #1 can be found in the work around section.

###@###.### 2003-11-25

Fix to parse3.cpp:

--- /export/rasbold/c2_baseline2/webrev4957832/src/share/vm/opto/parse3.cpp-    Thu Dec  4 16:28:03 2003
+++ parse3.cpp  Wed Dec  3 12:38:51 2003
@@ -366,26 +366,33 @@ void Parse::do_multianewarray() {
 
   // fill the lowest dimensions with unknown sizes
   for (int index = 0; index < mdimensions - ndimensions; index++) {
     const TypeAry* arr0 = TypeAry::make(prev_type, TypeInt::POS);
     prev_type = TypeAryPtr::make(TypePtr::BotPTR, arr0, prev_array, true, 0);
     prev_array = NULL; // array klasses can be lazy, except the first
   }
 
   // Fill in the dimensions with known sizes (passed in the JVM stack)
   for (int i = 0; i < ndimensions; i++) {
-    Node* count_val = length[i];
-    // try to get a better type than POS for the size
-    const Type* count_type = count_val->bottom_type()->join(TypeInt::POS);
+    const Type* count_type = TypeInt::POS;
+    TypePtr::PTR ptr = TypePtr::BotPTR;
+    // For the outermost dimension, try to get a better type than POS for the
+    // size.  We don't do this for inner dimmensions because we lack the 
+    // support to invalidate the refined type when the base array is modified
+    // by an aastore, or when it aliased via certain uses of an aaload.
+    if (i == ndimensions - 1) {
+      count_type = length[i]->bottom_type()->join(count_type);
+      ptr = TypePtr::NotNull;
+    } 
     assert(count_type->is_int(), "must be integer");
     const TypeAry* arr0 = TypeAry::make(prev_type, (TypeInt*)count_type);
-    prev_type = TypeAryPtr::make(TypePtr::NotNull, arr0, prev_array, true, 0);
+    prev_type = TypeAryPtr::make(ptr, arr0, prev_array, true, 0);
     prev_array = NULL; // array klasses can be lazy, except the first
   }
   const TypeAryPtr* arr = (const TypeAryPtr*)prev_type;
 
   address fun = NULL;
   switch (ndimensions) {
    case 1: fun = OptoRuntime::multianewarray1_Java(); break;
    case 2: fun = OptoRuntime::multianewarray2_Java(); break;
    case 3: fun = OptoRuntime::multianewarray3_Java(); break;
    case 4: fun = OptoRuntime::multianewarray4_Java(); break;

###@###.### 2003-12-05
                                     
2003-12-05
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.2_05
generic
tiger-beta

FIXED IN:
1.4.2_05
tiger-beta

INTEGRATED IN:
1.4.2_05
tiger-b32
tiger-beta

VERIFIED IN:
1.4.2_05


                                     
2004-06-14



Hardware and Software, Engineered to Work Together