Showing posts with label PermGen. Show all posts
Showing posts with label PermGen. Show all posts

Friday, September 4, 2026

Java/Tomcat: Understanding Out of Memory Error (OOME)

Out of Memory Error (OOME) in Tomcat

What is an Out of Memory Error, and why does it happen?

The basic cause of an OutOfMemoryError (OOME) is that the JVM cannot allocate enough memory for an application to continue running. In a Tomcat environment, this can result in an application failure or, depending on the situation, the Tomcat process being unable to continue.

The error itself is not particularly difficult to understand. The difficult part is finding the actual root cause.

A stack trace may show where the JVM ran out of memory, but it does not always identify why the application consumed so much memory. In many cases, the problem is related to the web application running inside Tomcat rather than Tomcat itself.

The code causing the problem may also look perfectly normal. For example, an application might load a large amount of data into memory, retain objects longer than necessary, or create too many objects during processing. This makes it difficult to identify which part of the application is actually responsible for the problem.

Here are some common causes of an OutOfMemoryError:

  • The JVM heap size is too small for the application's workload.
  • The application loads a very large file or a large amount of data into memory.
  • The application creates a large number of objects or collections.
  • Objects are unintentionally retained for longer than necessary, causing memory usage to grow.
  • Excessive recursion can cause a StackOverflowError rather than a heap OutOfMemoryError, so this should be considered a separate problem.
  • Too many threads can cause memory-related problems, although this may also result in errors such as Unable to create new native thread.
  • Running out of file descriptors is a separate operating-system resource issue and is not itself an OutOfMemoryError.
  • In older Java applications, a large number of web applications or classloaders could contribute to PermGen exhaustion.

Finding the Root Cause

Increasing the JVM heap size can sometimes reduce or temporarily resolve an OutOfMemoryError, but it does not necessarily fix the underlying problem. If the application continues to consume memory, increasing -Xmx only delays the failure.

For this reason, it is important to investigate the application's memory usage using appropriate JVM monitoring or profiling tools and identify which objects or parts of the application are consuming memory.

Note: PermGen applies to older Java versions. Java 8 removed PermGen and replaced it with Metaspace. Therefore, PermGen space errors are relevant mainly when troubleshooting older Java applications.

Error: java.lang.OutOfMemoryError: PermGen space

In J2EE development, this is one of the common and frequent errors that developers may face. Sometimes it can be difficult to identify the actual cause, especially when the application runs out of JVM memory.

PermGen space or heap size (OutOfMemoryError) issues can be addressed by increasing the JVM memory allocated to Tomcat. The following are some approaches that can be used.
 

Solution 1: Set CATALINA_OPTS

Set the `CATALINA_OPTS` environment variable before starting Tomcat.
 

Linux / Unix — ksh / bash

export CATALINA_OPTS="-Xms512m -Xmx512m"

Linux / Unix — tcsh / csh

setenv CATALINA_OPTS "-Xms512m -Xmx512m"

Windows

set CATALINA_OPTS="-Xms512m -Xmx512m"

Stop the Tomcat server, set the `CATALINA_OPTS` environment variable, and then restart Tomcat.

You can check `tomcat-install/bin/catalina.sh` or `catalina.bat` to see how `CATALINA_OPTS` is used.
 

CATALINA_OPTS vs JAVA_OPTS


In `catalina.bat` or `catalina.sh`, you may notice that `CATALINA_OPTS`, `JAVA_OPTS`, or both can be used to specify JVM options.

The difference is that `CATALINA_OPTS` is intended specifically for Tomcat, whereas `JAVA_OPTS` can also be used for other Java applications.

I prefer to use `CATALINA_OPTS` when configuring options specifically for Tomcat, so that Tomcat does not unnecessarily pick up JVM options intended for other applications.
 

Solution 2: Change catalina.bat

Another option is to modify the `catalina.bat` file under the Tomcat `bin` directory.

Open:

tomcat-install/bin/catalina.bat
 

Search for:
 

CATALINA_OPTS, If `CATALINA_OPTS` is not already configured, you can set the required JVM options there.

For older Java versions, an example configuration was:

-Xms256m -Xmx512m -XX:MaxPermSize=256m

If this does not work, check the command used to start Java near the end of the `catalina.bat` file. Look for a line containing `%_EXECJAVA%` and `%JAVA_OPTS%`.

The JVM options can be added to that command. For example:


%_EXECJAVA% %JAVA_OPTS% -Xms256m -Xmx512m -XX:MaxPermSize=256m %DEBUG_OPTS% -Djava.endorsed.dirs="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%

In this example, `CATALINA_OPTS` has been removed from the command to avoid specifying the same JVM parameters more than once.
 

Important Note About MaxPermSize

`-XX:MaxPermSize` applies to older Java versions that used the PermGen memory area. Java 8 removed PermGen and replaced it with Metaspace.

Therefore, for Java 8 and later, do not use:

-XX:MaxPermSize=256m

For modern Java versions, the relevant options are typically `-Xms` and `-Xmx` for heap size, and `-XX:MaxMetaspaceSize` can be used when there is a specific need to limit Metaspace.

The exact JVM options should depend on the Java version being used by Tomcat.