Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4860265

JVM crashes with dump in 1.2.2_011 because of invalid last_freep in compactHeap

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P3 P3
    • None
    • 1.2.2_011
    • hotspot
    • x86
    • windows_2000

      TThe licensee reported a crash in 1.2.2_011 (windows). They did not use JIT.
      They looks at dump and report their analysis for hotspot code.

      BEHAVIOR:
       They runs their application in 1.2.2_011 and it outputs a core file.

       =====>
        ...
        504bf8ce 85ff test edi,edi
                                          // edi(=prev_free) is NULL
        504bf8d0 7408 jz jvm!compactHeap+0x21a (504bf8da)
        504bf8d2 8b4c2430 mov ecx,[esp+0x30]
        504bf8d6 8939 mov [ecx],edi
        504bf8d8 eb0b jmp jvm!compactHeap+0x225 (504bf8e5)
        504bf8da e8b1020000 call jvm!findBlock+0x60 (504bfb90)
                                          // Call lastFreeBlock(). return val is NULL.
        504bf8df 8b4c2430 mov ecx,[esp+0x30]
        504bf8e3 8901 mov [ecx],eax
                               // Write the rerun val of lastFreeBlock() to last_freep
        504bf8e5 8b11 mov edx,[ecx]
                                          // Get last_freep
        504bf8e7 5f pop edi
        504bf8e8 8915d0f15050 mov [jvm!last_free_block (5050f1d0)],edx
                                          // last_free_block <= last_freep
        504bf8ee 8b01 mov eax,[ecx]
                                          // Get last_freep
        504bf8f0 5e pop esi
        504bf8f1 5d pop ebp
        504bf8f2 8b08 mov ecx,[eax] ds:0023:00000000=????????
                                          // Crash here on refering last_freep()
        504bf8f4 5b pop ebx
        504bf8f5 83e1f8 and ecx,0xfffffff8
        504bf8f8 890d84f55050 mov [jvm!last_free_len (5050f584)],ecx
        504bf8fe 83c41c add esp,0x1c
        504bf901 c3 ret
        .....
        <====


      INVESTIGATION:

      They find out the above crash instruction is corresponding to the following
      (3) in compactHeap(). (.\src\share\javavm\runtime\gc.c)

      == compactHeap() ===>
      ....
        memset((char *)free_list_bin, 0, sizeof(free_list_bin));
                                        // initialize free_list_bin[]
        prev_free = NULL;
        while( /* All objects **/) {
                 ....
              /** GC **/ ------(1)
                ....
        }
       
        if (prev_free) ------(2)
            *last_freep = prev_free;
        else
           *last_freep = lastFreeBlock();

        sysAssert(*last_freep == 0 || obj_free(*last_freep));
            
        #ifdef VERBOSEGC
            last_free_block = *last_freep;
            last_free_len = obj_len(*last_freep); ----(3) // CRASH occurs
        #endif /* VERBOSEGC */
       }
       ...

      <=== compactHeap() ===
        
      They consider the crash (above (3))is caused by the invalid value of the
      last_freep.
      According to the above (2), they think
        - prev_free is NULL
        or
        - return value of lastFreeBlock() is NULL
        
      They looked into lastFreeBlock() first.
        
      ===>
      ..
      static unsigned char *
      lastFreeBlock(void)
      {
          int i = NUM_FREE_LIST_BINS - 1;
          unsigned char ** lastp = &free_list_bin[i];
          while (i >= 0) {
              unsigned char * p = *lastp;
              while (p) {
                  lastp = FREE_LIST_NEXTP(p);
                  if (*lastp == NULL)
                      return p;
                  p = *lastp;
              }
              i--;
              lastp--;
          }
         return NULL;
      }
      ...
      <===

      According to the code, lastFreeBlock() returns NULL when all the
      free_list_bin[] are NULL.

      Next, they look into prev_free. In the (1) of compactHeap(), the program
      does
       - If there is free block, the pointer of the free block is substituted for
          prev_free.
       - If there is any non-movable object, the program does the following and
         registers the block to free_list_bin.
          
        ...
         if (prev_free) {
             addBlock(prev_free);
             prev_free = NULL;
          }
       ...
          
      Therefore, they suspect the fllowing senario whcih makes the last_freep NULL
      at (3).

      ##
       When the progarm can not find any free block in (1)(GC execuing),
       the program flow goes "false" at (2) and the value of lastFreeBlock()
       is NULL at (3) becasue free_list_bin[] is not updated in (1).
       
       In other words, this crash seems to happen when GC at (1) can not release
       any object.


      CONCLUSION :
       
       The crash senario is,
         i) GC occurs when some new objects are created.
         ii) There is no free block(page) which is released by GC of i).
         iii)In spite of no free block in i) and ii), the program try searching
             the last free block and releasing objects by free() system call.
         iV) At iii), the program does not take consideration of ii) case,
             which is no free object by GC. as the result, the program
             refer NULL and JVM crash.
             
      LICENSEE REQUEST:
        If the senario is reasonable, the fix is needed.
        
        
      NOTE:
       More details request, please see comment section.

      ==========================================================================

            minqi Yumin Qi
            tbaba Tadayuki Baba (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: