JDK-4414162 : Classloading: Exponential mem. use, and slow (in nested try/catch)
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2001-02-11
  • Updated: 2001-10-31
  • Resolved: 2001-10-31
Related Reports
Relates :  
Description

Name: boT120536			Date: 02/11/2001


orig synopsis:  "Exponetntial memory use on classload and long classload times"

java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Server VM (build 2.0fcs-E, mixed mode)


The problem appears to be that the JVM classloader handles nested try/catch
blocks badly. I created a class that has nested try/catch blocks and on class
load it took approximately 1gb ram to load it. (I watched the java process's
memory allocation) I have tried this code on Solaris, 2k and RedHat Linux with
jdks 1.2.1, 1.2.2, and 1.3 as well as HotSpot with -server and -client on 2k
and linux and the problem appears in all cases.
  Factors that affect the bug are:
  1)How deeply nested the blocks are. I have had the problem pop up with only
one outer try/catch with 200 inner try/catch blocks. The deeper the nesting the
lees inner blocks needed to cause the problem.
  2)The number of try/catch blocks. Cutting down on the try/catch blocks
changes how much ram is used on class load
  3)The complexity of the try/catch blocks. Finally blocks and returns inside
of the try/catch blocks cause the problem to happen with fewer blocks.

  The memory usage is exponential. 130 blocks may take 20mb to load while 150
will take 40 and 200 will take 100mb, the deeper the nesting the faster the
growth.
  Garbage collection also appears to be effected. If GC happens while the
thread is executing inside of the block it can take up to 15 seconds to finish.
In one case where I had a total of 130 blocks gc happened 3 times at 15 seconds
per for a total of a 45 seconds to execute the block(about 150k of ram used in
the block). When the blocks were flattened out the GC times went away. However,
by increasing the eden size on the VM GC didn't happen inside of the block as
often so the problem wasn't as pronounced.
  I found this bug due to machine generated code (notably when Weblogic and
  Tomcat generate jsp pages with custom tags) but normal code may be slightly
affected as well. Below is a class that, just by loading, should take about a
GB of ram. Just do a class.forName to load it.
  Thanx for your time!
  -Jeff Ward

p.s.
  The submission of the full class file gave me an error so I cut out a chunk
of 149 try/catch blocks. Just copy/paste the one I left 150 times to re build
it before your compile.


public class Severe
{

  private Severe(String arg)
  {
    try
    {
      try
      {
        try
        {
          try
          {
            try
            {
              try
              {
                try
                {
                  try
                  {
                    try
                    {
                      try
                      {
                        try
                        {
                          try
                          {
                            try
                            {
                              try
                              {
                                try
                                {
                                  try
                                  {
                      <************* repeat this block 150 times ******>
                                    try
                                    {
              
                                      if (arg.equals("test")) return;
                                    }catch(Exception e){
                                    }finally{
                                      if (arg.equals("test")) return;
                                    }
                      <************* repeat this block 150 times ******>
			

                                    if (arg.equals("test")) return;
                                  }catch(Exception e){
                                    if (arg.equals("test")) return;
                                  }finally{
                                    if (arg.equals("test")) return;
                                  }
            
                                  if (arg.equals("test")) return;
                                }catch(Exception e){
                                  if (arg.equals("test")) return;
                                }finally{
                                  if (arg.equals("test")) return;
                                }
          
                                if (arg.equals("test")) return;
                              }catch(Exception e){
                                if (arg.equals("test")) return;
                              }finally{
                                if (arg.equals("test")) return;
                              }
        
                              if (arg.equals("test")) return;
                            }catch(Exception e){
                              if (arg.equals("test")) return;
                            }finally{
                              if (arg.equals("test")) return;
                            }
              
                            if (arg.equals("test")) return;
                          }catch(Exception e){
                            if (arg.equals("test")) return;
                          }finally{
                            if (arg.equals("test")) return;
                          }
            
                          if (arg.equals("test")) return;
                        }catch(Exception e){
                          if (arg.equals("test")) return;
                        }finally{
                          if (arg.equals("test")) return;
                        }
          
                        if (arg.equals("test")) return;
                      }catch(Exception e){
                        if (arg.equals("test")) return;
                      }finally{
                        if (arg.equals("test")) return;
                      }
        
                      if (arg.equals("test")) return;
                    }catch(Exception e){
                      if (arg.equals("test")) return;
                    }finally{
                      if (arg.equals("test")) return;
                    }
            
                    if (arg.equals("test")) return;
                  }catch(Exception e){
                    if (arg.equals("test")) return;
                  }finally{
                    if (arg.equals("test")) return;
                  }
          
                  if (arg.equals("test")) return;
                }catch(Exception e){
                  if (arg.equals("test")) return;
                }finally{
                  if (arg.equals("test")) return;
                }
        
                if (arg.equals("test")) return;
              }catch(Exception e){
                if (arg.equals("test")) return;
              }finally{
                if (arg.equals("test")) return;
              }
      
              if (arg.equals("test")) return;
            }catch(Exception e){
              if (arg.equals("test")) return;
            }finally{
              if (arg.equals("test")) return;
            }
			
            if (arg.equals("test")) return;
          }catch(Exception e){
            if (arg.equals("test")) return;
          }finally{
            if (arg.equals("test")) return;
          }
          
          if (arg.equals("test")) return;
        }catch(Exception e){
          if (arg.equals("test")) return;
        }finally{
          if (arg.equals("test")) return;
        }
        
        if (arg.equals("test")) return;
      }catch(Exception e){
        if (arg.equals("test")) return;
      }finally{
        if (arg.equals("test")) return;
      }
      
      if (arg.equals("test")) return;
    }catch(Exception e){
      if (arg.equals("test")) return;
    }finally{
      if (arg.equals("test")) return;
    }
  }
}
(Review ID: 114930) 
======================================================================

Comments
WORK AROUND Name: boT120536 Date: 02/11/2001 Increase the eden size (-xx:NewSize and -XX:MaxNewSize) on jdk 1.3 to get around some of the GC speed issues. ====================================================================== -noverify will speed things up if security issues are not a problem. ###@###.### 2002-05-06
06-05-2002

EVALUATION This bug has been closed as "Will Not Fix" due to a strategic redirection of resources to Java 1.4. If bug needs to be fixed in an old release then an escalation will need to be filed. Bugs which are escalations from external customers will continue to be addressed by the support team. Internal customers may escalate bugs by filing them as priority 1 (P1) bugs. ###@###.### 2001-10-31
31-10-2001