Troubleshooting Tomcat Errors (And How to Fix Them)
Though it's one of the most popular app servers for Java developers, Apache Tomcat can be tricky to figure out at first. If you are troubleshooting Tomcat, you've come to the right place. In this blog, we'll cover some of the most common Tomcat errors and how to fix them. We'll also explain specific issues related to request routing, garbage collection, application logging, and session management — and provide solutions so you can get the most out of your Tomcat deployments.
How to Approach Troubleshooting Tomcat
Troubleshooting can involve investigating various aspects such as Tomcat configuration, logs, server health, and network connectivity.
Knowing where to look is the first step in quickly diagnosing and resolving issues. Here are some common Tomcat errors and possible solutions.
Back to top10 Common Tomcat Errors
1. java.net.BindException: Address already in use
: Verify if the port specified in the server xml
configuration file is already in use. You can change the port in the Connector
element.
2. java.lang.OutOfMemoryError
: Modify the JVM memory settings in the catalina.sh
or catalina.bat
file. You can set the JAVA_OPTS
environment variable to increase the heap size.
3. FAIL - Application at context path [/myApp] could not be started
: Check the logs in the catalina.out
or localhost.log
files for more details on why the application failed to start.
4. HTTP Status 404 - The requested resource is not available
: Verify that the URL and the context path for your application are correct. Ensure that your application is deployed and the context path matches. More on this topic later in this blog.
5. java.util.zip.ZipException: invalid entry size
: Check your WAR file for corruption. If you have unzip
installed, try listing the files in the .war file by doing: unzip -l myapp.war.
unzip
will indicate if there is a structural issue with the .war file.
6. javax.net.ssl.SSLHandshakeException
: Check your TLS configuration in the server.xml
file. Ensure that the keystore and truststore files are correctly configured by using keytool
located in the JDK bin
directory to list the certificates in the store: keytool -v -list -keystore /path/to/keystore
Usually there is an intermediate certificate missing from the truststore that can cause handshake exceptions. It can be easy to forget the difference between a keystore and a truststore and import a certificate into the wrong store. A keystore is used to verify public certificates presented to Tomcat by a client, and a truststore defines which certificate authorities Tomcat can trust.
7. HTTP Status 403 - Access to the requested resource has been denied
: Check your security constraints in the web.xml
file and ensure that the user has the necessary roles and permissions. For example, the following constraint that requires authentication for any GET
and POST
requests is defined in the web.xml
servlet:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.openlogic.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>tomcat</role-name>
</auth-constraint>
The role-name
in the auth-constraint,tomcat
must be defined in the tomcat-users.xml
file located in Tomcat’s conf
directory:
<tomcat-users..>
<role rolename="tomcat"/>
<user username="jdoe" password="s3cret" roles="tomcat"/>
</tomcat-users>
8. org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class...
: There are many causes of this exception. The first place to check is in the context.xml
of the web application and verify the database connection pool configuration is correct. Ensure that the JDBC driver is correctly specified, which can vary among different drivers.
9. org.apache.jasper.JasperException: Unable to compile class for JSP: An error occurred at line: 13 in the jsp file: /WebContent/test.jsp
In this example, the syntax error is indicated on line 13 of test.jsp. The issue may start at line 13, but the actual syntax error may be further down the file. Typically code brackets ‘<%’ and ‘%>’ are not placed properly in the JSP file. Using a tool like 'vi'
or 'nano'
can be tough to pinpoint issues. Instead, use a code editor that has visual tools to highlight incorrect syntax.
10. java.security.AccessControlException
: This usually indicates an issue in Tomcat's conf/catalina.policy
file. An application may be deployed needing access to classes or file system resources in Tomcat (not recommended). Decisions to modify this file should be taken into careful consideration since an attacker could take advantage of any policy changes.
Back to topBack to topGet the Enterprise Guide to Apache Tomcat
In this free guide, OpenLogic Tomcat experts discuss key strategies for enterprises to improve their Tomcat deployments with real-life examples and analysis.
Tomcat Request Routing
Request routing is directing incoming HTTP requests to the correct application based on certain criteria. Troubleshooting request routing depends on if URL mapping, virtual hosts, reverse proxy, or load balancing is being used. Let’s take a brief look at each one.
The first place to look is in catalina.out
for any exceptions when the app is started and fix those.
Check the URL mapping in the web.xml
of the application. If you have a servlet named MyServlet
mapped to "/myapp", all requests to http://mydomain.com/myapp/* will be routed to that servlet:
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myapp/*</url-pattern>
</servlet-mapping>
Check the localhost_access_log.yyyy-mm-dd.txt
for any 404 or 50x errors.
Are virtual hosts being used to allow multiple domains to be configured on a single Tomcat instance? Inspect the server.xml
for any XML snippets like the following:
<Host name="mydomainA.com" appBase="webapps/myappA">
<Alias>www.mydomainA.com</Alias>
</Host>
In this example, there is one domain defined that is mapped to a directory in Tomcat’s webapps directory. Check the appBase
location that is relative to Tomcat’s installation directory for the presence of these applications.
If Tomcat is behind a reverse proxy server (e.g. Apache HTTP Server, NGINX), the proxy can handle the initial request and then forward it to Tomcat based on certain rules. The reverse proxy can perform request routing based on URL patterns, headers, or other criteria. The mod_proxy
module handles this logic for Apache HTTP Server. Verify the ProxyPass
and ProxyPassReserve
directives in httpd.conf
of Apache HTTP Server:
ProxyPass /myapp http://localhost:8080/myapp
ProxyPassReverse /myapp http://localhost:8080/myapp
Check the error log located in /var/log/apache2/error.log
or /var/log/httpd/error_log
for mod_proxy
issues:
LogLevel debug
If the Apache Tomcat Connector module, mod_jk
, is used to connect Apache HTTP Server with Apache Tomcat, then there are a few things to check when troubleshooting.
First, find the location of the mod_jk.log
file by searching any *.conf
files including httpd.conf
for the JkLogFile
directive:
JkLogFile /etc/httpd/logs/mod_jk.log
Open this file and check for any connection related issues such as:
[error] ajp_get_reply::jk_ajp_common.c (2020): (node1) Timeout with waiting reply from tomcat. Tomcat is down, stopped or network problems (errno=110)
The JkLogLevel
file can be changed from info
to debug
if needed for further troubleshooting. This change requires a restart of Apache HTTP Server.
Verify that the workers defined in the worker.properties
file are correctly configured. The location of worker.properties
file is set by the JkWorkersFile
.
A typical worker.properties
looks like:
worker.list=jkstatus,lb_router
worker.lb_router.type=lb
worker.jkstatus.type=status
worker.lb_router.balance_workers=tomcat-node1,tomcat-node2
worker.lb_router.sticky_session=1
worker.tomcat-node1.port=8009
worker.tomcat-node1.host=tomcat_node1.openlogic.com
worker.tomcat-node1.type=ajp13
worker.tomcat-node1.lbfactor=1
worker.tomcat-node2.port=8009
worker.tomcat-node2.host=tomcat_node2.openlogic.com
worker.tomcat-node2.type=ajp13
worker.tomcat-node2.lbfactor=1
In this example, Apache HTTP Server will distribute requests equally across two Apache Tomcat nodes on Tomcat’s AJP port (8009) with sticky sessions enabled.
Check the worker.<workername>.host
and worker.<workername>.port
settings to make sure they match the Tomcat server's configuration in server.xml
:
<Connector protocol="AJP/1.3"
address="::1”
port="8009" /
From the Apache HTTP Server node, verify that port 8009 is open to the Apache Tomcat nodes.
In addition, confirm that mod_jk
handles the routing for the application to Apache Tomcat by checking the JkMount
directive:
JkMount /myapp/* lb_router
Also, make sure there is a route for each worker in Tomcat’s server.xml
:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat-node1">
jvmRoute
should match one of the workers defined in worker.properties
:
worker.lb_router.balance_workers=tomcat-node1,tomcat-node2
Tomcat Garbage Collection
If you're seeing long JVM pause times related to garbage collection, it's usually the result of using an outdated or deprecated garbage collection algorithm or poor tuning. All of the following JVM arguments can be set in Tomcat’s bin/setenv
file. A few key points to keep in mind:
- It is invaluable to have a suite of repeatable performance test scripts to achieve a baseline and then to track performance as changes are made to the JVM arguments. Apache JMeter is an excellent open source tool to use to create these scripts. This is the most important takeaway of this section.
- Before any changes are made enable garbage collection logging by specifying the following in the
JAVA_OPTS
:
This will keep five historical files of size 100MB in /tmp
and prints the system time and time of the garbage collection. There are several open source tools available to analyze this output for problems.
- Use the G1GC algorithm since it outperforms the default garbage collector in JDK 8 (Parallel GC) or CMS by specifying
-XX:+UseG1GC
in theJAVA_OPTS
variable. G1GC is the default on Java 11, but it is not the default on Java 8. Many people do see further improvements in Tomcat performance when using G1GC on JDK 11. Please note G1GC still does require tuning.
- Set the minimum heap size
(-XX:InitialHeapSize)
and the maximum heap size(-XX:MaxHeapSize)
to the same value to avoid dynamic heap allocation during the runtime of the application.
- Set a max pause time goal for garbage collection on the JVM. The default is set to 200 milliseconds, which is a soft goal. Try to stay within 200 to 500 milliseconds, and this is set by the following JVM argument:
-XX:MaxGCPauseMillis=<milliseconds>
- Set
-XX:+UseStringDeduplication
to reduce memory footprint of String objects on the heap. This is disabled by default.
- Set the max metaspace size for class metadata kept in native memory. Start with 256MB and test by specifying:
-XX:MaxMetaspaceSize=256m
There are many other JVM arguments to consider setting, but this list is good to start with.
Back to topTomcat Application Tuning
Tomcat application logging is a great way to trace exactly what is going on in an application, but it can be difficult to know what packages to enable logging on because there are so many components. It is imperative that an application keep its own log separate from Tomcat’s standard out (catalina.out
), so that application logging does not clutter up catalina.out
as this can make troubleshooting more difficult.logging.properties
in Tomcat’s conf
directory is the main configuration file for logging. Knowing the format of the file including the log level, package, handler (file or console) is important to get just the right amount of output to troubleshoot an application without filling up the disk or bringing production down. If the log level is too high or the package to log is too broad (i.e.org.apache.level = FINEST
), this can cause the JVM to be CPU-bound at 100% utilization or saturate the disk with write requests causing IO wait.
There is the access log valve that can be configured in Tomcat’s server.xml
that can assist with understanding what requests are coming into the server and how they are handled.
Examples and discussion on these log mechanisms can be found in my blog on application logging in Tomcat.
Back to topTomcat Session Management
The easiest way to troubleshoot Tomcat session management is by increasing the log level for session-related activity or generating a heap dump to see what is actually being kept in session.
To log all session-related activity in the servlet container (Catalina) in a single node deployment, declare this statement in Tomcat’s conf/logging.properties
:
org.apache.catalina.session.level=ALL
If the HA clustering component of Tomcat is being used in a multi-node deployment, then specify the following:
org.apache.catalina.ha.level=FINE
This will produce a lot of logging statements in catalina.out
, so make sure that enough disk space is available.
There are a few different mechanisms to capture a heap dump, but I will cover the easiest way in this blog.
To generate a heap dump right when the JVM runs out of heap add the following JVM argument to the JAVA_OPTS
variable in Tomcat's bin/setenv
:
JAVA_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof”
Ensure the path of the heap dump has plenty of disk available as multi-gigabyte heaps can cause an undesirable “disk is full” situation. Tomcat must be restarted for this change to take effect.
A heap dump can also be triggered on demand by issuing the following command on a running JVM:
jmap -dump:live,format=b,file=/path/to/dump.hprof <JVM process ID>
jmap
is located in the bin directory of the JDK.
Users sometimes store objects in heap that are much larger than what they anticipated, which include JDBC result sets or log handlers.
Back to topFinal Thoughts
Hopefully, these fixes will help you troubleshoot Tomcat and keep things running smoothly. For more information about working with Tomcat, including best practices for patching, upgrading, memory configuration, and security, download the Enterprise Guide to Apache Tomcat.
Still Struggling With Tomcat? Talk to an OpenLogic Expert
Technical support from OpenLogic is backed by SLAs and provided directly from Enterprise Architects with 15+ years of open source experience. We can help you troubleshoot and optimize your Tomcat deployment(s) for long-term success.
Additional Resources:
- Guide - Apache Tomcat Overview
- Datasheet - Tomcat Support and Services
- Blog - Apache Tomcat Clustering: The Ultimate Guide
- Blog - How to Install Apache Tomcat
- Blog - Tomcat 11 Preview
- Webinar - Modernizing Your Java Application With Open Source