web analytics

Data, data everywhere 

Twitter LinkedIn RSS
magnify
Home Java EE Java EE development: the PermGen error
formats

Java EE development: the PermGen error

When developing a tiered Java EE database application there are a tremendous number of program errors that will only be discovered at runtime. If one is using Hibernate as the Object-relational mapping tool, even JPQL queries embedded within your Java application will (likely) pass Java compilation because the syntax and semantics of the JPQL query isn’t checked at compile time, but only at runtime when the Hibernate JPA library attempts to convert the JPQL query into an SQL query for the specific DBMS used by the application. In my case, recently that database has been Oracle 12c but the same principle applies to any DBMS.

Two things in particular exacerbate the runtime error issue when working with Java EE. First are the heavy use of Java annotations (or XML files if you like to avoid annotations) for configuring the interactions between the Java application, the ORM mapper (in my case, Hibernate), and the underlying DBMS. Second is the (certain) requirement to use native SQL queries within your application, because it will be the rare application that doesn’t require either (a) an SQL language feature that Hibernate does not support, such as outer joins over derived tables, or (b) a more streamlined, set-oriented result set, such as one that uses SQL analytic functions, that return a concise result from the server in a single SQL request.

I’ve written about using native SQL queries with JPA and Java annotations previously; a recent blog post by Lukas Eder nicely outlines the issues with native queries and JPA. However, these problems exist even for JDBC applications since (again) there is no compile-time checking of SQL queries.

Consequently, one usually goes through many compile/run/debug cycles in developing a Java EE database application. For this reason it is essential to ensure that the majority of your program code executes within Java try/catch blocks, and that when exceptions are thrown then an indication of the error is output. When using GlassFish as the application server, the server’s log files (by default in the C:\glassfish4\glassfish\domains\domain1\logs directory) will contain any error stack traces generated by printStackTrace() methods from anywhere within your application.

Another error that can come up is a known out-of-memory condition with the Java VM, caused by a memory leak in the class loader when deploying Java EE applications to GlassFish repeatedly. When using Eclipse to deploy the application, the error can manifest itself in a couple of different ways, but the end result is that the deployment will fail and it may not be obvious within Eclipse’s IDE that the PermGen error has occurred. However, a look at the GlassFish server’s current log file will normally confirm the problem:

1
2
3
4
5
6
7
8
9
10
11
12
[2015-08-25T13:05:27.893-0400] [glassfish 4.1] [WARNING] [] [javax.enterprise.ejb.container] [tid: _ThreadID=27 _ThreadName=http-listener-1(1)] [timeMillis: 1440522327893] [levelValue: 900]
 
[[javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean: java.lang.OutOfMemoryError: PermGen space
	at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionClientTx(EJBContainerTransactionManager.java:665)
	at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:507)
	at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
	at com.sun.ejb.containers.StatefulSessionContainer.postInvokeTx(StatefulSessionContainer.java:1853)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
	at com.sun.proxy.$Proxy398.open(Unknown Source)

The workaround is to simply bounce the GlassFish server, easy to do from within Eclipse using the “Servers” view.

Alas, inconsistencies with SQL queries from within a Java EE application aren’t the only source of runtime errors for developers; there are others. More on another class of such errors in my next post.

 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
3 Comments  comments 

3 Responses

  1. Since Java 1.8, the JVM doesn’t use the Perm Gen space anymore, switching to Metaspace, so most class-related objects are not stored in the native memory. Are you using Java 1.7 or other older JVM version?

    • Glenn Paulley

      Thanks for that tip, Vlad. You are right – my GlassFish 4.1 installation is still using Java 7. Do you know if the switch away from PermGen completely solves this issue, or is the leak still present and will manifest itself in a different way?

      • If it’s because of a class-loading issue, then it will just delay the out-of-memory failure.

        On a large Java EE system, you can get tons of classes loaded by system/application/module class-loaders so this puts a lot of pressure on the JVM PermGen memory.

        In this case, you can connect with VisualJVM while starting the server to monitor the PermGen memory allocation. If it throws the error and the server hasn’t yet started, you might want to raise the PermGen memory threshold as a JVM parameter.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>