United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6505535 jmap -histo options print negative number for large set of objects
JDK-6505535 : jmap -histo options print negative number for large set of objects

Details
Type:
Bug
Submit Date:
2006-12-18
Status:
Closed
Updated Date:
2011-03-08
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
core-svc
OS:
linux,generic
Sub-Component:
tools
CPU:
x86,generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
6,7
Fixed Versions:

Related Reports
Backport:
Duplicate:
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-b105, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.9-22.20.ELsmp #1 SMP Fri Nov 18 03:04:44 EST 2005 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
When we try to use jmap -histo to display the heap information, we find that sometimes it will print negative number due to integer overflow. This manifest itself fairly often as our application tends to use large heap size on 64bit platform.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Build a jvm instance with instance of a class that is more then 2G in size - you can use program I have attached

2) run this on a 64-bit JVM, with java -Xmx4G LargeObjectArrayList

3) Once the Array list allocation has finished, it prints "Press return to stop". You should then use jmap -histo to obtain a histogram of the heap

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The total number of bytes used by all the instance of the class, with size > 0
ACTUAL -
When you run jmap -histo for the test case, you will see the following:

num   #instances    #bytes  class name
--------------------------------------
  1:       330   -1431629248  [Ljava.lang.Object;
  2:     10000      640000  LargeObjectSize$LargeObject
  3:      4588      555040  <methodKlass>
  4:      4588      526456  <constMethodKlass>
  5:       304      334336  <constantPoolKlass>
  6:      6852      304904  <symbolKlass>
  7:       283      235264  <constantPoolCacheKlass>
  8:       304      212672  <instanceKlassKlass>
  9:       345      146984  [I
 10:      1032      121712  [C
 11:       494       99104  [B
<output removed to save space>
190:         1          16  java.lang.String$CaseInsensitiveComparator
191:         1          16  java.lang.reflect.ReflectAccess
  Total    32419   -1428175088

Notice that the array of objects at the top printed with negative number, as well as the total.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.ArrayList;

public class LargeObjectArrayList {

        public class LargeObject {
                long a,b,c,d,e;
        }

        private ArrayList<LargeObject> justStore = new ArrayList<LargeObject>(10000);

        public LargeObjectSize() {
                for(int i=0; i<10000; i++) {
                        justStore.add(new LargeObject());
                }
        }

        public static void main(String[] args) throws Exception {
                LargeObjectArrayList los = new LargeObjectArrayList();
                System.out.println("Press return to stop");
                System.in.read();
        }
}

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

                                    

Comments
EVALUATION

The output format of the total size was hardcoded for 32-bit integer which fails to deal with large heap memory.
                                     
2007-03-30
SUGGESTED FIX

------- heapInspection.cpp -------
55,57c55,58
<   st->print_cr("%9d   %9d  %s",
<                _instance_count,
<                _instance_words * HeapWordSize,
---
>   // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
>   st->print_cr("%13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u  %s",
>                (jlong)  _instance_count,
>                (julong) _instance_words * HeapWordSize,
157,158c158,160
<   jint total = 0;
<   size_t totalw = 0;
---
>   // simplify the formatting (ILP32 vs LP64) - store the sum in 64-bit
>   jlong total = 0;
>   julong totalw = 0;
160c162
<     st->print("%3d: ", i+1);
---
>     st->print("%4d: ", i+1);
165c167,168
<   st->print_cr("Total %8d   %9d", total, totalw * HeapWordSize);
---
>   st->print_cr("Total %13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u",
>                total, totalw * HeapWordSize);
224,225c227,228
<                    "num   #instances    #bytes  class name\n"
<                    "--------------------------------------",
---
>                    " num     #instances         #bytes  class name\n"
>                    "----------------------------------------------",
                                     
2007-03-30



Hardware and Software, Engineered to Work Together