Out of memory error: permGen space

Hello I am having issue running an embedded graph.

This graph is executed ~4000 times to load a separate file.

I have tweaked various jvm settings to no avail bumping permGen memory up to 512 and I still only get through about 1400 iterations. I’ve also turned on various garbage collection settings as well with little to no difference.

The database is postgres connection config is:

user=postgres
jdbcSpecific=POSTGRE
password=password
name=name
database=POSTGRE
dbURL=jdbc\:postgresql\://localhost/dbname
threadSafeConnection=true

Java code is below:


   log.debug("Initializing Clover Engine");
   EngineInitializer.initEngine(env.getString("paths.clover.engine") + "plugins", env.getString("paths.clover.project") + "workspace.prm", null);
   EngineInitializer.forceActivateAllPlugins();

   GraphRuntimeContext runtimeContext = new GraphRuntimeContext();
   TransformationGraph graph = null;
   InputStream graphInputStream = null;
   InputStream propsInputStream = null;
   Properties props = new Properties();

   try
   {
      log.debug("Getting graph input stream");
      graphInputStream = new FileInputStream(pathToGraph);
      
      if (pathToProps != null)
      {
         log.debug("Props file passed in, loading");
         propsInputStream = new FileInputStream(pathToProps);
         props.load(propsInputStream);
      }
      
      log.debug("Adding project directory to props");
      props.put("PROJECT_DIR", env.getString("paths.clover.project"));
   
      log.debug("Loading Graph");
      TransformationGraphXMLReaderWriter graphReader = new TransformationGraphXMLReaderWriter(props);
      graph = graphReader.read(graphInputStream);
      
      log.debug("Initializing Graph");
      graph.init();
            
      log.debug("Running Graph");
      WatchDog watchDog = new WatchDog(graph, runtimeContext);
      IThreadManager threadManager = new SimpleThreadManager();
      Future<Result> futureResult = threadManager.executeWatchDog(watchDog);
      
      Result result = Result.N_A;
         
      result = futureResult.get();
      log.debug("Finished, result:" + result.toString());
   }
   catch (Exception ex)
   {
      log.error("Failed to run Clover graph", ex);
   }

I’ve commented out code to see where in the process the extra memory is consumed and it occurs when calling graph.init();

I have also tried calling EngineInitializer.initGraph(graph, runtimeContext); with the same result.

Calling graph.free() at the end of each iteration has no effect either.

I downloaded yourkit java profiler and started looking into the class loaders as this is an area yourkit suggests is where permGen space errors can occur.

In looking at the class loaders there appears to be one org.jetel.util.classloader.GreedyURLClassLoader class loaded for each iteration of the graph being executed.

Below is a memory snapshot


Paths from "GC Roots" to "Object GreedyURLClassLoader #2005028"

+---------------------------------------------------------------+-----------------+----------------+
|                             Name                              |  Retained Size  |  Shallow Size  |
+---------------------------------------------------------------+-----------------+----------------+
|  +---org.jetel.util.classloader.GreedyURLClassLoader          |         44,048  |            72  |
|    |                                                          |                 |                |
|    +---<loader> of org.postgresql.Driver                      |         47,600  |           416  |
|    | |                                                        |                 |                |
|    | +---driverClass of java.sql.DriverInfo                   |         47,640  |            24  |
|    |   |                                                      |                 |                |
|    |   +---[75] of java.lang.Object[161]                      |      4,765,584  |           656  |
|    |     |                                                    |                 |                |
|    |     +---elementData of java.util.Vector                  |      4,765,608  |            24  |
|    |       |                                                  |                 |                |
|    |       +---drivers of java.sql.DriverManager [Class]      |      4,766,928  |           344  |
|    |                                                          |                 |                |
|    +---<loader> of org.postgresql.core.Logger                 |            320  |           320  |
|    | |                                                        |                 |                |
|    | +---<class> of org.postgresql.core.Logger                |          1,128  |            32  |
|    |   |                                                      |                 |                |
|    |   +---logger of org.postgresql.Driver                    |         47,600  |           416  |
|    |     |                                                    |                 |                |
|    |     +---driverClass of java.sql.DriverInfo               |         47,640  |            24  |
|    |       |                                                  |                 |                |
|    |       +---[75] of java.lang.Object[161]                  |      4,765,584  |           656  |
|    |         |                                                |                 |                |
|    |         +---elementData of java.util.Vector              |      4,765,608  |            24  |
|    |           |                                              |                 |                |
|    |           +---drivers of java.sql.DriverManager [Class]  |      4,766,928  |           344  |
|    |                                                          |                 |                |
|    +---classloader of java.security.ProtectionDomain          |            760  |            32  |
|      |                                                        |                 |                |
|      +---<protection domain> of org.postgresql.Driver         |         47,600  |           416  |
|        |                                                      |                 |                |
|        +---driverClass of java.sql.DriverInfo                 |         47,640  |            24  |
|          |                                                    |                 |                |
|          +---[75] of java.lang.Object[161]                    |      4,765,584  |           656  |
|            |                                                  |                 |                |
|            +---elementData of java.util.Vector                |      4,765,608  |            24  |
|              |                                                |                 |                |
|              +---drivers of java.sql.DriverManager [Class]    |      4,766,928  |           344  |
+---------------------------------------------------------------+-----------------+----------------+

Generated by YourKit Java Profiler 8.0.24 Apr 21, 2010 3:39:08 PM

At this point I am pretty stuck so I appreciate any suggestions as what to do next.

Thank you in advance.

-John

Hello John,
The graph connection uses external linked library. All external libraries are loaded to the memory for each single graph execution. And these libraries very often contain common memory leak which causes that the library classes can’t be garbage-collected when the graph execution finishes.So memory space for java classes (PermGen space) is sooner or later full and result is this exception: “java.lang.OutOfMemoryError: PermGen space”.
I can propose you two possible solutions:

  • don’t run whole code in the loop, but recycle the graph:
loop:  
      WatchDog watchDog = new WatchDog(graph, runtimeContext);  
      IThreadManager threadManager = new SimpleThreadManager();  
      Future<Result> futureResult = threadManager.executeWatchDog(watchDog);  
       
      Result result = Result.N_A;  
           
      result = futureResult.get();  
      graph.reset();  
:end_loop  
  • don’t use external library, i.e. set driver on the classpath, instead of in connection configuration:
user=postgres  
jdbcSpecific=POSTGRE  
password=password  
name=name  
dbURL=jdbc\:postgresql\://localhost/dbname  
dbDriver=org.postgresql.Driver  
threadSafeConnection=true  

Thank you for your help.

Changing the connection.cfg to use the postgres driver in the class path worked great.