Deep Analysis and Optimization Strategies for "JARs that were scanned but no TLDs were found in them" Warning in Tomcat 9

Dec 04, 2025 · Programming · 15 views · 7.8

Keywords: Tomcat 9 | TLD Scanning | Performance Optimization | JAR Files | Startup Time

Abstract: This paper provides an in-depth exploration of the "JARs that were scanned but no TLDs were found in them" warning that occurs during Tomcat 9 startup. By analyzing the TLD scanning mechanism, it explains that this warning is not an error but an optimization hint from Tomcat to improve performance. Two main solutions are presented: adjusting log levels to ignore the warning, and enabling debug logging to identify JAR files without TLDs and add them to a skip list, thereby significantly enhancing startup speed and JSP compilation efficiency. Supplementary methods, including automated script-based JAR identification and flexible scanning configurations in Tomcat 9, are also discussed, offering comprehensive guidance for developers on performance optimization.

Background and Nature of the Issue

During the startup of Tomcat 9, developers often encounter the following log message:

INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

This is not an error or bug, but a performance hint from the Tomcat container after scanning JAR files for TLDs (Tag Library Descriptors) during initialization. Tomcat defaults to scanning all JAR files to locate TLD resources, which are essential for supporting JSP tag libraries. However, many JAR files (e.g., database drivers, utility libraries) do not contain TLDs, and scanning them consumes unnecessary system resources, prolonging startup time.

Detailed Explanation of TLD Scanning Mechanism

TLD scanning in Tomcat is handled by the org.apache.jasper.servlet.TldScanner class, which traverses all JAR files in the WEB-INF/lib directory and classpath during container startup to check for .tld files. This process is crucial for supporting custom JSP tags but impacts performance in the following ways:

Below is a simplified example code illustrating how Tomcat checks JAR files:

public class TldScanner {
    public void scanJars(File jarFile) {
        try (JarFile jar = new JarFile(jarFile)) {
            Enumeration<JarEntry> entries = jar.entries();
            boolean hasTld = false;
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                if (entry.getName().endsWith(".tld")) {
                    hasTld = true;
                    processTld(entry); // Process TLD file
                }
            }
            if (!hasTld) {
                logWarning(jarFile.getName()); // Log warning for no TLD
            }
        } catch (IOException e) {
            handleError(e);
        }
    }
}

Solution 1: Adjusting Log Levels

If the warning does not affect application functionality and developers wish to reduce log clutter, it can be suppressed by modifying log configuration. In Tomcat's conf/logging.properties file, add or change the following line:

org.apache.jasper.servlet.TldScanner.level = SEVERE

This sets the log level for TldScanner to SEVERE, recording only severe errors and ignoring informational scan warnings. This method is quick and easy but does not improve scanning performance; it only optimizes log output.

Solution 2: Optimizing Scanning Performance

To fundamentally enhance performance, it is recommended to identify and skip JAR files without TLDs. The steps are as follows:

  1. Enable Debug Logging: In logging.properties, set:
    org.apache.jasper.compiler.TldLocationsCache.level = FINE
    org.apache.jasper.servlet.TldScanner.level = FINE
    After restarting Tomcat, the log will list all JAR files scanned without TLDs in detail.
  2. Edit the Skip List: Open the conf/catalina.properties file and locate the tomcat.util.scan.StandardJarScanFilter.jarsToSkip property. Add the JAR filenames (without paths) from the debug log to this list, separated by commas. For example:
    tomcat.util.scan.StandardJarScanFilter.jarsToSkip = \
    mysql-connector-java-8.0.23.jar,\
    gson-2.8.6.jar,\
    slf4j-api-1.7.30.jar
  3. Verify Effectiveness: Restart Tomcat and observe if startup time decreases and warning messages reduce.

This method significantly improves startup speed and JSP processing efficiency by reducing unnecessary scan operations, especially beneficial for applications with many third-party dependencies.

Supplementary Methods: Automation and Advanced Configuration

For complex environments, manually managing JAR lists can be tedious. Referring to other answers, automated scripts can be used:

#!/bin/sh
TOMCAT_HOME=/opt/tomcat
for i in `find $TOMCAT_HOME -follow -name "*jar"`
do
    jar tvf $i | grep -i tld > /dev/null
    if [ $? -ne 0 ]; then
        echo "$(basename $i),\\"
    fi
done

This script iterates through all JAR files in the Tomcat directory, checks for TLDs, and outputs a list of files without TLDs, facilitating batch addition to the skip configuration.

Additionally, Tomcat 9 supports more flexible scanning strategies. In catalina.properties, you can set:

tomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar

This skips all JAR files, then explicitly specifies JARs to scan (e.g., those containing TLDs) via the jarsToScan property. This approach is suitable for scenarios demanding peak performance but requires ensuring no necessary TLD resources are missed.

Conclusion and Best Practices

When addressing Tomcat's TLD scan warnings, developers should choose strategies based on actual needs:

By deeply understanding Tomcat's scanning mechanism and implementing the optimizations discussed, developers can eliminate redundant warnings and significantly enhance overall application performance, demonstrating professional mastery of Java EE container management.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.