JDK-6233169 : Permspace can become corrupted if positioned at 0x80000000
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.2_07
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: sparc
  • Submitted: 2005-02-25
  • Updated: 2012-10-08
  • Resolved: 2005-03-23
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.
Other JDK 6
1.4.2_09Fixed 6 b29Fixed
Description
Permspace can get corrupted on Solaris Sparc 7,8,9 if it is positioned at
0x80000000. This is reproducible even with one of the demo programs:

| 1. get hold of a complete J2SE 1.4.2_07 (for example) SDK installation.
|    One of mine happens to live at /opt_earth/java/j2sdk1.4.2_07/.  Adapt
|    path names below suitably.-- Make sure DISPLAY is set, but this is
|    just so the JVM has something nice to do.
| 
| 2. cd /opt_earth/java/j2sdk1.4.2_07
|    bin/java -Xms300m -Xmx768m -XX:MaxPermSize=1440m \
|      -jar demo/jfc/Java2D/Java2Demo.jar
|    (from another terminal window) locate the pid of this java process,
|    and
|    pmap $pid
| 
| 3. Inspect the pmap output.  Find the segment or two which make up the
|    java heap.  The permanent generation segment will be the next one
|    above these in the address space, i.e. the next one below these in
|    pmap output.  For example, this might look like:
|    ...
|    6F380000      8K read/write/exec     [ anon ]
|    6F400000  34112K read/write/exec     [ anon ] <<<<java heap
|    74950000 273088K read/write/exec     [ anon ] <<<<java heap
|    9F400000   6912K read/write/exec     [ anon ] <<<<perm gen
|    F9580000      8K read/write/exec     [ anon ]
|    Note that the segments are spaced such that there's room to grow the
|    heap to 768m, and room to grow the perm gen to 1440m, and additional
|    red zone padding between segments.
|    Note also that these segments are created from higher towards lower
|    addresses.  The 0x9F400000 was chosen by the kernel to accommodate
|    a 1440m segment plus redzone padding, given that another segment
|    already started at 0xF9580000.  Thus the requested MaxPermSize
|    determines where the perm gen segment will start  (the stuff at
|    higher addresses will not vary much from one run to the next;  but
|    it will depend on the exact sizes of several shared libraries, and
|    thus will vary depending on Solaris version and patch levels.)
| 
| 4. Work out how much larger MaxPermSize will need to be in order to
|    get the base address of the perm gen segment just below 0x80000000,
|    but the already-occupied part of it extends above .  This
|    may take a few trial and error iterations, since small changes are
|    sometimes absorbed by the padding.  For example:
|    bin/java -Xms300m -Xmx768m -XX:MaxPermSize=1940m \
|      -jar demo/jfc/Java2D/Java2Demo.jar
|    ...
|    4FF7C000     96K read/write/exec   /usr/dt/lib/libXm.so.4
|    50000000  34112K read/write/exec     [ anon ]
|    55550000 273088K read/write/exec     [ anon ]
|    80000000   6400K read/write/exec     [ anon ]
|    F9500000    352K read/exec         /opt_earth/java/j2sdk1.4.2_07/jre/lib/sparc/libawt.so
|    ...
|    and I got the same at 1942m, but the next 2-MBy increment did the
|    trick on my system:
| 
| 5. bin/java -Xms300m -Xmx768m -XX:MaxPermSize=1944m \
|      -jar demo/jfc/Java2D/Java2Demo.jar
|    Exception in thread "main" java.lang.NoSuchMethodError: sun.awt.image.InputStreamImageSource: method <init>()V not found
|            at sun.awt.image.URLImageSource.<init>(URLImageSource.java:23)
|            at sun.awt.SunToolkit.createImage(SunToolkit.java:529)
|            at java2d.DemoImages.getImage(DemoImages.java:87)
|            at java2d.DemoImages.<init>(DemoImages.java:72)
|            at java2d.Java2Demo.<init>(Java2Demo.java:113)
|            at java2d.Java2Demo.main(Java2Demo.java:478)
| 
|    This is le bug.
| 
|    The progress-bar graphics in the preliminary window will have frozen
|    up showing "Loading image" (for example - the victim class would
|    depend on where exactly each class falls in the perm gen segment
|    which now straddles the 0x80000000 line),  and the java process is
|    sitting there doing nothing, ready to debug with everything you can
|    think of throwing at it - SIGQUIT, pmap, gcore, dbx, SA...
|    In my case, the address space layout around the perm gen segment was
|    now:
|    4FB7C000     96K read/write/exec   /usr/dt/lib/libXm.so.4
|    4FC00000  34112K read/write/exec     [ anon ]
|    55150000 273088K read/write/exec     [ anon ]
|    7FC00000   4352K read/write/exec     [ anon ]
|    F9500000    352K read/exec         /opt_earth/java/j2sdk1.4.2_07/jre/lib/sparc/libawt.so
|    so of those 4352K's worth of page table mappings already created in
|    the perm gen, there are 4096k in 0x7FC00000-7FFFFFFF and 256k above
|    0x80000000.
| 
| 6. It seems that similar problems can also happen when the perm gen is
|    above 0x80000000 but the java heap crosses the 0x80000000 mark, or
|    even when the java heap is strictly below and the perm gen is strictly
|    above this  (and some copying of stuff from the heap to the perm gen
|    occurs),  but this is not as easy to reproduce with a small demo such
|    as the Java2D one - you'd need to run something which loads far more
+    classes and exercises garbage collection seriously.

2.4   Describe problem impact to the customer. (optional)

###@###.### 2005-2-25 14:28:42 GMT

Comments
EVALUATION I'm unable to reproduce this problem, using the example method shown. 1$ uname -a SunOS analemma 5.8 Generic_108528-29 sun4u sparc SUNW,Ultra-60 1$ /java/re/jdk/1.4.2_07/promoted/latest/binaries/solaris-sparc/bin/java -Xms300m -Xmx768m -XX:MaxPermSize=1940m -jar /java/re/jdk/1.4.2_07/promoted/latest/binaries/solaris-sparc/demo/jfc/Java2D/Java2Demo.jar 2$ /bin/ps -ef | grep 1.4.2 pbk 17527 17526 14 15:14:53 pts/20 0:15 /java/re/jdk/1.4.2_07/promoted/latest/binaries/solaris-sparc/bin/java -Xms300m 2$ pmap 17527 17527: /java/re/jdk/1.4.2_07/promoted/latest/binaries/solaris-sparc/bin/java .... 50000000 34240K read/write/exec [ anon ] 55550000 273088K read/write/exec [ anon ] 80000000 7168K read/write/exec [ anon ] .... and Java2Demo seems to run just fine. Another way to know where the various parts of the Java object heap are is to run with -XX:+PrintHeapAtGC, which produces maps like: Heap before GC invocations=0: Heap def new generation total 33152K, used 16043K [0x50000000, 0x52150000, 0x55550000) eden space 32192K, 49% used [0x50000000, 0x50faafc0, 0x51f70000) from space 960K, 0% used [0x51f70000, 0x51f70000, 0x52060000) to space 960K, 0% used [0x52060000, 0x52060000, 0x52150000) tenured generation total 273088K, used 0K [0x55550000, 0x66000000, 0x80000000) the space 273088K, 0% used [0x55550000, 0x55550000, 0x55550200, 0x66000000) compacting perm gen total 7168K, used 6945K [0x80000000, 0x80700000, 0xf9400000) the space 7168K, 96% used [0x80000000, 0x806c8578, 0x806c8600, 0x80700000) where you can see that the "compacting perm gen" starts at 0x80000000. (And you can see from the fact that the perm generation is the only that's nearly full that this collection is from a failed attempt to allocate in the perm generation.) Of course, this way of looking at the heap only works if the VM runs long enough to cause a collection, and doesn't hang with the NoSuchMethodError you show. I've tried other sizes for the -XX:MaxPermSize= to get the permanent generation to start at various other places near the 2^31 boundary. E.g., compacting perm gen total 7168K, used 6949K [0x79c00000, 0x7a300000, 0xf9400000) the space 7168K, 96% used [0x79c00000, 0x7a2c9638, 0x7a2c9800, 0x7a300000) and compacting perm gen total 7168K, used 6951K [0x86400000, 0x86b00000, 0xf9400000) the space 7168K, 96% used [0x86400000, 0x86ac9db0, 0x86ac9e00, 0x86b00000) to see if *crossing* that boundary was the problem, but I've been unable to reproduce the problem. Why am I unable to reproduce the problem? Especially that you gave such clear instructions. We did used to have bugs like this with spaces laid out across the 2^31 boundary, but I think we fixed them all a while ago. We might have inadvertently introduced a new one. But if I can't reproduce the problem it will be hard to track down. ###@###.### 2005-2-25 23:35:10 GMT I'm now able to reproduce the problem, on a recent JDK-1.6.0 fastdebug build. We seem to have failed a binary search lookup. Since no garbage collection has happened, this is not a GC problem. I'm reassigning it to the runtime group, even though I think it might be fun to track this one down. I've attached the hs_err file from the fastdebug failure, and the dbx stack trace. ###@###.### 2005-03-01 18:18:56 GMT I'm pretty sure the problem is this line in symoblOop.hpp: return (int)(intptr_t(this) - intptr_t(other)); where those casts (that look like constructors!) should be to uintptr_t's, since the symbolOops can be on either side of the sign-bit. Then there's the cast of the difference to an int, but I think that's okay as long as the symbolOops aren't too far apart, e.g., in 64-bit VMs with huge permanent generations. If no one uses anything except the sign of the result, it might be better to just compute -1, 0, or 1, rather than trying to fit the difference into an int. ###@###.### 2005-03-02 18:37:49 GMT
25-02-2005