Overview of the Problem
ColdFusion runs on the Java Virtual Machine (JVM). An “Out of memory” (OOME) error occurs when the JVM cannot allocate more memory for the type of object or operation being requested. In ColdFusion, you’ll typically see errors such as java.lang.OutOfMemoryError: Java Heap space, GC overhead limit exceeded, Metaspace, or Unable to create new native thread. These errors crash requests, hang the server, or trigger automatic restarts, causing downtime.
Why it happens:
- The heap (objects/data) or metaspace (class metadata) is exhausted.
- Too many threads are created or stacks are too large.
- Native/direct buffers or off-heap memory leak.
- Inefficient code or misconfiguration drives memory spikes beyond the JVM limits.
Understanding which OOME you have is the key to fixing it quickly.
Possible Causes
Types of OutOfMemoryError You May See
- Heap space: The object heap is full; GC can’t free enough space.
- GC overhead limit exceeded: The JVM is spending too much time in GC with little progress.
- Metaspace (or PermGen on older Java/CF): Class metadata area is full due to frequent class loading or classloader leaks.
- Direct buffer memory: Off-heap buffers (NIO, PDF/image libs) are exhausted.
- Unable to create new native thread: OS limits or excessive thread creation; stack size too large.
ColdFusion-Specific Culprits
- Large in-memory PDFs (cfdocument), images (cfimage), or spreadsheets (cfspreadsheet).
- Storing huge objects in Application/Session/Server scopes.
- Unbounded query result sets; missing cfqueryparam; queries pulling millions of rows.
- Memory leaks from libraries, classloader leaks after hot-deploys, or repeated loading of Custom tags/components.
- ORM/Hibernate second-level cache misconfigurations or aggressive caching.
- Excessive concurrent cfthread usage or blocking Scheduled tasks.
- Insufficient or mis-sized JVM memory (Xmx, metaspace).
- In-process HTTP session storage in clustered nodes, causing session bloat.
Quick Cause/Solution Reference (bulleted pairs)
- Cause: Large cfdocument/cfimage operations.
- Solution: Stream or chunk; reduce resolution/quality; use temporary files and optimize output.
- Cause: Massive result sets in memory.
- Solution: Paginate; SELECT only needed columns; use cfqueryparam; stream to disk.
- Cause: Session/Application scope bloat.
- Solution: Store only small references; shorten timeouts; externalize sessions (Redis/database).
- Cause: Metaspace growth via hot-redeploy/classloader leaks.
- Solution: Restart; fix hot-deploy; cap metaspace; avoid repeated dynamic class loading.
- Cause: Too many threads or large stacks.
- Solution: Reduce thread pools/concurrency; shrink -Xss; tune Tomcat connector.
- Cause: JVM too small for workload.
- Solution: Increase -Xmx and -XX:MaxMetaspaceSize; adopt G1GC.
Step-by-Step Troubleshooting Guide
Step 1: Confirm the Error Type and Scope
- Check logs:
- ColdFusion logs: cfusion/logs/exception.log, coldfusion-out.log, application.log.
- Catalina/Tomcat logs: logs/catalina.out, localhost.*.log.
- Look for lines like:
java.lang.OutOfMemoryError: Java Heap space
java.lang.OutOfMemoryError: Metaspace
java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: Unable to create new native thread
- Determine if the OOME is request-specific or systemic (e.g., occurs during nightly batch jobs).
Step 2: Enable Diagnostic Logging and Dumps
Add these to ColdFusion’s jvm.config (CF 2018/2021/2023) or in setenv.bat/.sh via JAVA_OPTS/CATALINA_OPTS:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/coldfusion/heapdumps
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xlog:gc*:file=/opt/coldfusion/logs/gc.log:time,uptime,level,tags (Java 11+)
Then restart the service. When the next OOME occurs, a .hprof heap dump is written for analysis.
Optional live diagnostics:
- FusionReactor or ColdFusion PMT (Performance Monitoring Toolset) to track heap, metaspace, threads.
- jcmd/jmap/jstack/VisualVM/JMC for on-the-fly inspection.
Step 3: Analyze Heap Dumps
- Use Eclipse MAT or VisualVM:
- Open the .hprof file; run Leak Suspects.
- Identify largest dominators (e.g., byte[] from PDFs, large ArrayList from cached queries, BufferedImages).
- Check GC roots for Application/Session/Server-scoped references or static collections.
- If metaspace OOME:
- Inspect for many classloaders or repeated Deployment cycles.
- Look for frameworks/plugins loaded repeatedly.
Step 4: Review ColdFusion Configuration and Scopes
- ColdFusion Administrator:
- Check Server settings → Memory Variables and Caching.
- Review Session/Application timeouts and the size of data stored in those scopes.
- For Enterprise: use the Server monitor or PMT to inspect slow requests and memory usage.
- Application.cfc:
- Ensure sessionManagement is necessary and timeouts are sensible.
- Avoid storing large query results or binary blobs in Application/Session.
- ColdFusion caching (template/function/query cache):
- Ensure cache sizes and eviction policies are appropriate.
Step 5: Right-Size and Tune the JVM
- For Java 11+ (CF 2018+, 2021, 2023):
- Prefer G1GC:
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+UseStringDeduplication
- Set heap sizing:
- -Xms and -Xmx the same to avoid runtime resizing.
- Use a realistic upper bound based on RAM and other services (keep OS/headroom).
- Example:
-Xms4g
-Xmx4g
-XX:MaxMetaspaceSize=512m
- Thread stacks:
-Xss512k (or 256k on Linux; test stability)
- If using older CF/Java with PermGen:
-XX:MaxPermSize=256m
Step 6: Code-Level Fixes (CFML and Libraries)
- Reduce PDF/image memory:
- cfdocument: lower DPI, paginate, avoid massive inline images, stream output.
- cfimage: resize/compress; avoid loading huge images at full resolution.
- Stream large data:
- Use cfcontent/cffile to stream; avoid reading entire files into variables.
- For spreadsheets, use streaming libraries or write incremental files.
- Limit query sizes:
- Add WHERE clauses, pagination (LIMIT/OFFSET or ROWNUM).
- Use cfqueryparam; fetch only necessary columns.
- Avoid storing Big data in scopes:
- Keep only IDs/keys; fetch details on demand.
- Consider external caches (Redis, memcached) for large objects.
- Fix leaks:
- Ensure finally blocks close resources (file streams, cfhttp connections).
- Avoid unbounded lists/maps in singletons or static variables.
- Validate ORM caching; turn off second-level cache if misused.
- Control concurrency:
- Limit cfthread usage; use named thread pools where possible.
- Stagger Scheduled tasks and long-running jobs.
Example: common memory-heavy pattern and fix
cfml
SELECT * FROM Users
SELECT id, name FROM Users ORDER BY id OFFSET
Step 7: Infrastructure and Tomcat/Web Connector
- Tomcat connector and thread pools:
- Limit maxThreads to a sane value; too many threads increases memory footprint.
- server.xml example:
<Connector port=”8500″ protocol=”HTTP/1.1″
maxThreads=”200″
acceptCount=”100″
connectionTimeout=”20000″ />
- Externalize sessions:
- For clusters, avoid in-memory Session replication for large sessions; use J2EE sessions backed by Redis/DB, or reduce session payload.
- OS limits:
- Increase ulimit (Linux) or Windows job object limits if you see “Unable to create new native thread”.
- Monitor container memory limits if running in Docker/Kubernetes.
Configuration Examples
ColdFusion jvm.config snippet
java.args=-Xms4g -Xmx4g -Xss512k -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UseStringDeduplication \
-XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/coldfusion/heapdumps \
-Xlog:gc*:file=/opt/coldfusion/logs/gc.log:time,uptime,level,tags
setenv.sh (Tomcat) example
export CATALINA_OPTS=”$CATALINA_OPTS -Xms4g -Xmx4g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/cf/heapdumps”
Sample OOME log excerpt
2025-09-18 14:02:55 ERROR coldfusion.runtime.MemoryRuntime – OutOfMemoryError
java.lang.OutOfMemoryError: Java heap space
Dumping heap to /opt/coldfusion/heapdumps/java_pid12345.hprof …
Heap dump file created [2039481234 bytes in 35.315 secs]
Common mistakes and How to Avoid Them
- Only increasing -Xmx without analysis:
- You may mask leaks and create longer GC pauses. Always perform heap dump analysis.
- Caching everything:
- Unbounded caches create slow memory creep. Set size limits and expirations.
- Storing large queries/blobs in Session/Application:
- Leads to bloat and longer request times. Store only keys or small DTOs.
- Ignoring metaspace:
- Hot-reloading Custom tags/components repeatedly can leak classloaders. Cap metaspace and fix the redeploy process.
- Excessive maxThreads/cfthread usage:
- More threads ≠ more throughput if DB/IO bound; it increases memory and context switching.
- Not enabling heap dumps:
- Without dumps, root cause analysis is guesswork.
- Using 32-bit JVM or low container limits:
- Caps usable memory severely. Use a 64-bit JVM and check Docker/K8s memory limits.
- Leaving image/PDF processing at defaults:
- High DPI and large images blow up memory; always downscale/optimize.
Prevention Tips / Best practices
- Size memory based on load tests and profiling; match -Xms to -Xmx and keep OS headroom.
- Use G1GC on Java 11+; monitor pause times and GC logs regularly.
- Enable heap dumps and GC logs in production with rotation policies.
- Establish coding guidelines:
- Paginate DB results; avoid SELECT *.
- Stream files; avoid holding large buffers in memory.
- Keep scopes lean; small timeouts for Session.
- Monitor continuously:
- ColdFusion PMT, FusionReactor, or JMX dashboards for heap, metaspace, threads, and slow requests.
- Review scheduled tasks and batch jobs:
- Run off-peak; limit concurrency; process in chunks.
- Validate third-party libraries:
- Keep dependencies updated; test for leaks; avoid hot-reload in production.
- For clustering:
- Externalize sessions and keep session payload small; avoid in-memory replication of large objects.
- Perform regular restart windows if you rely on Features known to accumulate state (last resort, not a fix), while you work on root causes.
Key Takeaways
- Identify the exact OOME type first; solutions differ for heap, metaspace, GC overhead, direct buffers, and threads.
- Always enable heap dumps and GC logging to replace guesswork with evidence.
- Fix the root cause: reduce memory-heavy operations, right-size JVM, keep scopes lean, and control concurrency.
- Use G1GC on modern Java and set realistic heap/metaspace caps with monitoring.
- Prevent recurrence through Coding Standards, load testing, and continuous monitoring.
FAQ
How do I quickly tell whether the OOME is heap or metaspace?
Check the error message in exception.log or catalina.out. “Java heap space” and “GC overhead limit exceeded” indicate heap stress; “Metaspace” indicates class metadata exhaustion. Enable heap dumps and review MAT leak suspects for clarity.
Should I switch to G1GC on ColdFusion 2021/2023?
Yes, G1GC is the recommended garbage collector for Java 11+ and balances throughput with predictable pauses. Combine with -XX:MaxGCPauseMillis and review GC logs to fine-tune.
What’s the safest way to handle large PDFs or images in ColdFusion?
Prefer streaming and incremental processing. Lower DPI/quality, paginate PDFs, resize images early, and avoid loading entire binary data into memory. Use temporary files when appropriate.
Can session storage cause OutOfMemory errors?
Yes. Large objects stored in Session/Application scopes accumulate. Reduce payload, shorten timeouts, and consider external session storage (Redis/database) for clusters or high-volume sites.
How do I analyze a heap dump securely in production environments?
Copy the .hprof off the server to a secure analysis workstation. Use Eclipse MAT/VisualVM offline. Ensure the dump is treated as sensitive data (it can contain snippets of content), and delete it after analysis following your data retention policy.
