Why upgrading the JVM behind ColdFusion improves Performance
Adobe ColdFusion runs on top of a Java Virtual Machine (JVM). Upgrading that JVM (and tuning it correctly) can yield substantial gains: faster startup, lower latency under load, more efficient Garbage collection, stronger TLS/crypto, and better native Performance on newer CPUs. It also keeps the platform within vendor support windows and receives important Security fixes. Done carefully, a JVM upgrade is a low-risk, high‑impact way to optimize your ColdFusion application server.
Prerequisites / Before You Start
-
Environment and version awareness
- Identify your ColdFusion edition and version (e.g., ColdFusion 2018, 2021, 2023) and the exact update/hotfix level.
- Verify the supported Java versions in the official ColdFusion-Java support matrix. As a general guide:
- CF 2023: Java 17 LTS (and later point releases within Adobe’s matrix).
- CF 2021: Java 11 LTS, and Java 17 LTS with later updates.
- CF 2018: Java 11 LTS with later updates (end of core support; confirm before proceeding).
- Confirm installed web server connectors (IIS/Apache via wsconfig) and embedded Tomcat version.
-
Backups and recovery plan
- Full filesystem backup of the ColdFusion installation directory (e.g., cfusion instance), especially:
- cfusion/bin/jvm.config
- cfusion/lib/ (any custom JARs)
- connectors (config/wsconfig)
- Backup ColdFusion Administrator settings (export via Admin if possible).
- Backup any added SSL certs in the old JVM’s truststore (cacerts).
- Database and other Integration credentials kept safe (for connectivity tests).
- Create a rollback plan: keep a copy of the old JDK/JRE folder and a copy of the original jvm.config.
- Full filesystem backup of the ColdFusion installation directory (e.g., cfusion instance), especially:
-
Staging and change management
- Prepare a non‑production environment to test the upgrade first.
- Define a Maintenance window and notify stakeholders.
- Line up monitoring tools (FusionReactor, New Relic, AppDynamics, Java Flight Recorder, or built‑in CF metrics) to compare before/after.
-
Choose a JDK vendor and version
- Preferred LTS JDKs: Eclipse Temurin (Adoptium), Azul Zulu, Oracle OpenJDK, Amazon Corretto, Red Hat.
- Ensure you Download a Server JDK, not a client‑only JRE. ColdFusion can run on a JRE, but a JDK is recommended for tooling and stability.
-
OS and permissions
- Admin/root privileges to install software and edit service configurations.
- Enough disk space for a parallel JDK install.
-
Dependency awareness
- Check for custom JVM flags currently in use (heap size, GC, PermGen settings, Security manager flags).
- Note Features that changed between Java 8 and 11/17 (e.g., PermGen removed in Java 8; Security Manager deprecated; unified GC logging; modules system; strong Encapsulation).
Step-by-Step Migration guide
1) Confirm supported Java targets
- Verify Adobe’s published support matrix for your ColdFusion and platform. Do not assume the newest JDK is always supported.
- Ensure your CF update level is current. Sometimes the ability to run on a newer JDK requires a specific ColdFusion update.
Tip: Keep a record of your baseline JVM flags from the ColdFusion Administrator (Java and JVM page) or cfusion/bin/jvm.config.
2) Install the new JDK side-by-side
-
Download and install the chosen JDK into a new folder, leaving the old JVM intact.
- Windows example path: C:\Java\jdk-17.0.11
- Linux example path: /opt/jdk/jdk-17.0.11
-
Verify the JDK:
C:\Java\jdk-17.0.11\bin\java -version
or
/opt/jdk/jdk-17.0.11/bin/java -version
-
Optional environment variables (not strictly required for ColdFusion but useful):
- JAVA_HOME = path to your JDK folder
- PATH = prepend %JAVA_HOME%\bin (Windows) or $JAVA_HOME/bin (Linux)
3) Back up ColdFusion’s JVM Configuration
-
Locate ColdFusion’s jvm.config (default instance “cfusion”):
- Windows: [CF root]\cfusion\bin\jvm.config
- Linux: /opt/coldfusion/cfusion/bin/jvm.config (actual path may vary)
-
Create a copy:
- jvm.config.backup-
- jvm.config.backup-
-
Also export settings from ColdFusion Administrator -> Java and JVM for reference.
4) Update java.home in jvm.config (or via CF Administrator)
You can change the JVM in two ways:
- Preferred: ColdFusion Administrator -> Java and JVM -> Java Virtual Machine Path, then “Submit Changes” and restart (the Admin writes to jvm.config).
- Manual: Edit jvm.config directly (use with care if the service is currently down or Admin is inaccessible).
Example jvm.config snippet to change the Java path:
Existing line
java.home=C:\Java\jdk-1.8.0_352
Replace with
java.home=C:\Java\jdk-17.0.11
Linux example:
java.home=/opt/jdk/jdk-17.0.11
Caution: Paths should not include trailing slashes. On Windows, escape backslashes if needed. Ensure file permissions remain correct.
5) Modernize JVM flags for Java 11/17+
Open jvm.config and review java.args. Remove or update deprecated options.
Common changes:
-
Remove PermGen flags on Java 8+:
- Delete -XX:PermSize and -XX:MaxPermSize (they cause startup failure on modern JDKs).
-
Prefer G1GC (default on Java 11/17) and tune gently:
-Xms2g
-Xmx2g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+UseStringDeduplication -
Replace legacy GC logging flags with unified logging (Java 11+):
-Xlog:gc*:file=/opt/coldfusion/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=20M
Windows path example:
-Xlog:gc*:file=C:/ColdFusion2023/cfusion/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=20M
-
If your app or libraries use deep reflection (more common when jumping from Java 8):
–add-opens=java.base/java.lang=ALL-UNNAMED
–add-opens=java.base/java.lang.reflect=ALL-UNNAMED
–add-opens=java.base/java.io=ALL-UNNAMED
–add-opens=java.base/sun.nio.ch=ALL-UNNAMEDAdd only as needed; Audit at runtime for IllegalAccess errors.
-
Consider class data sharing (CDS) to improve startup:
-Xshare:auto
-
Keep essential ColdFusion system properties (present by default in jvm.config). Do not remove Adobe-specific -D flags unless instructed by the vendor.
Table: Flags to remove or update when moving from older JVMs
| Legacy flag | Action on Java 11/17+ |
|——————————|—————————————-|
| -XX:PermSize, -XX:MaxPermSize| Remove |
| -XX:+PrintGCDetails, etc. | Replace with -Xlog:gc* unified logging |
| -XX:+UseConcMarkSweepGC | Remove; use G1GC (default) |
| -XX:+UseParNewGC | Remove; not used with G1 |
6) Migrate custom certificates to the new JDK truststore
If you imported SSL certificates into the old JVM cacerts (for outbound HTTPS calls, SAML, LDAP over TLS, etc.), migrate them:
-
List existing certs:
/bin/keytool -list -keystore /lib/security/cacerts -storepass changeit -
Export and import into the new JDK:
/bin/keytool -export -alias mycorp-root -keystore /lib/security/cacerts -file mycorp-root.cer -storepass changeit
/bin/keytool -import -alias mycorp-root -keystore /lib/security/cacerts -file mycorp-root.cer -storepass changeit
Consider using a dedicated truststore file and pointing to it with:
-Djavax.net.ssl.trustStore=/path/to/custom-truststore.jks
-Djavax.net.ssl.trustStorePassword=changeit
This avoids re-importing into cacerts during future upgrades.
7) Stop ColdFusion and restart with the new JVM
-
Windows (service names vary by version/instance):
net stop “ColdFusion 2023 Application Server”
net start “ColdFusion 2023 Application Server” -
Linux/systemd:
sudo systemctl stop coldfusion
sudo systemctl start coldfusion
If ColdFusion fails to start, immediately review cfusion/logs/coldfusion-out.log and coldfusion-error.log for JVM flag issues.
8) Validate the JVM version from ColdFusion
-
ColdFusion Administrator -> System Information: confirm Java version.
-
Run a quick CFML page:
Java version: #server.java.version#
Java Vendor: #server.java.vendor#
JVM Details: #server.system.properties[“java.vm.name”]# (#server.system.properties[“java.vm.version”]#)
-
Command-line sanity check:
“
\bin\java” -version
9) Performance tuning and smoke tests
- Start with conservative heap sizes (-Xms/-Xmx). Observe GC logs, CPU, and memory usage under load tests.
- For most ColdFusion workloads on Java 11/17, G1GC with moderate pause targets works well. Measure before aggressive tuning.
- Validate:
- Admin console pages
- Data source connections
- cfhttp calls to HTTPS endpoints
- PDF generation (Document services)
- CFSEARCH/ Solr if used
- Scheduling, mail, caching, REST endpoints, and WebSocket Features
Note: Some auxiliary services (e.g., Solr, PDFg) may use their own bundled JVMs and are not automatically upgraded with CF’s JVM. Check their service wrappers separately if needed.
10) Rollback plan
If problems arise:
- Stop ColdFusion.
- Restore the backed-up jvm.config (pointing java.home to the old JDK).
- Restart and confirm stability.
- Analyze logs to identify incompatible flags or missing certs, then retry the upgrade.
Risks, Common Issues, and How to Avoid Them
-
Incompatible Java version
- Symptom: Service fails to start immediately.
- Avoidance: Match CF update level to supported JDK per Adobe’s matrix. Test on staging.
-
Deprecated/removed JVM flags
- Symptom: “Unrecognized VM option” errors.
- Avoidance: Remove PermGen flags; replace legacy GC logging; remove CMS flags.
-
Missing SSL certificates
- Symptom: HTTPS requests fail with SSLHandshakeException.
- Avoidance: Migrate custom certs to new cacerts or a custom truststore; verify outbound TLS calls.
-
Strong Encapsulation and reflection errors (Java 11+/17+)
- Symptom: IllegalAccessException from reflective frameworks/libraries.
- Avoidance: Add targeted –add-opens for specific modules/packages; update problematic libraries.
-
Memory sizing pitfalls
- Symptom: Excessive GC pauses or OutOfMemoryError.
- Avoidance: Set reasonable -Xms/-Xmx; monitor GC logs; consider G1GC defaults before complex tuning.
-
Security manager and policy changes
- Symptom: Startup warnings or feature degradation.
- Avoidance: Remove obsolete -Djava.security.manager or adjust policies per vendor guidance.
-
Connectors not reconfigured
- Symptom: CF running but site 503/404 via IIS/Apache.
- Avoidance: The JVM upgrade does not normally affect connectors, but verify wsconfig is intact and services restarted.
-
Container memory limits (Docker/Kubernetes)
- Symptom: JVM ignores cgroup limits and over-allocates heap.
- Avoidance: On Java 11+, container awareness is on by default. Still verify -XX:MaxRAMPercentage or explicit -Xmx if needed.
-
Mixed 32-bit vs 64-bit binaries
- Symptom: Startup failure or poor memory ceiling.
- Avoidance: Ensure 64-bit JDK on 64-bit OS; align with your CF installation.
Post-Migration Checklist
-
Version and runtime
- ColdFusion Administrator shows the expected Java version and vendor.
- CFML page confirms server.java.version and vm name/version.
-
Functional validation
- Authentication and Session management work.
- Data sources and ORM (if used) connect.
- cfhttp to HTTPS endpoints succeeds.
- Scheduled tasks run on time.
- Mail (cfmail) sends successfully.
- PDF, image manipulation, spreadsheet, and document services function.
- REST endpoints and WebSocket channels operate correctly.
- File I/O, network calls, caching (EHCache or Redis), and Message queues (JMS/RabbitMQ/Kafka) behave as expected.
-
Performance sanity
- CPU and memory stable under peak test loads.
- GC logs show acceptable pause times and throughput.
- Startup time consistent with expectations.
-
Logs and monitoring
- No recurring stack traces or reflective access warnings.
- APM/monitoring dashboards clean.
- Baseline metrics recorded for future Comparison.
-
Security and crypto
- Required ciphers/TLS versions are available.
- All custom CA certs are present in the new truststore.
- Compliance scans (e.g., PCI) pass.
-
Housekeeping
- Document the new JDK version, install path, and JVM flags.
- Archive old JDK for rollback window; plan removal later.
- Update any Automation (Ansible, Chef, CI/CD) to provision the chosen JDK and flags.
Example configurations
Sample jvm.config (excerpt)
java.home=/opt/jdk/jdk-17.0.11
heap and GC
java.args=-Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UseStringDeduplication \
-Xlog:gc*:file=/opt/coldfusion/cfusion/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=20M \
-Xshare:auto \
Optional opens if needed by libraries
–add-opens=java.base/java.lang=ALL-UNNAMED \
–add-opens=java.base/java.lang.reflect=ALL-UNNAMED
Windows path style:
java.home=C:\Java\jdk-17.0.11
java.args=-Xms2048m -Xmx2048m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UseStringDeduplication ^
-Xlog:gc*:file=C:/ColdFusion2023/cfusion/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=20M ^
-Xshare:auto
Note: The actual jvm.config contains many additional -D properties. Keep Adobe-supplied flags in place.
Supported version pairings (guidance; verify your matrix)
| ColdFusion version | Typical supported Java LTS versions (verify exact updates) |
|---|---|
| CF 2023 | Java 17 LTS |
| CF 2021 | Java 11 LTS; Java 17 LTS (with later CF updates) |
| CF 2018 | Java 11 LTS (later CF updates; product in extended/EOL) |
Always consult the official Adobe ColdFusion release notes and support matrix to confirm compatibility before upgrading.
Practical tips for better performance after the upgrade
- Start with G1GC defaults; tune only after reviewing GC logs under realistic load.
- Right-size heap:
- Small to medium instances: 1–4 GB heap (-Xms/-Xmx).
- Large workloads: 4–8 GB+; ensure enough physical RAM remains for OS, caches, and off-heap.
- Consider -XX:MaxGCPauseMillis targets conservatively (e.g., 200–500 ms) and adjust empirically.
- Keep JVM arguments minimal and observable. Too many flags can complicate Troubleshooting.
- Use Java Flight Recorder (JFR) in pre-production load tests to find allocation hotspots.
- Avoid placing custom JARs in the JDK folders. Use ColdFusion’s lib directories or application classpaths.
Change management and safe rollout patterns
- Blue/green or canary Deployment
- Run a parallel ColdFusion instance pointing to the new JDK.
- Warm up caches and compile CFML on the green instance.
- Gradually shift traffic via load balancer/DNS.
- Snapshot/VM restore points
- Create snapshots before making JVM changes on VMs.
- Configuration as code
- Store jvm.config, Admin exports, and JVM flags in Version control.
- Automate with scripts so you can reproduce changes across environments.
Troubleshooting Quick reference
- Service won’t start: Check cfusion/logs/coldfusion-error.log; remove unknown JVM flags; confirm java.home path.
- SSL handshake failures: Import missing certs; verify truststore; check SNI and protocol versions.
- High CPU after upgrade: Inspect GC logs and thread dumps; verify G1GC settings; Audit hot code paths with JFR.
- Class/module errors on Java 17: Add specific –add-opens entries; upgrade outdated libraries.
- Memory pressure in containers: Use -XX:MaxRAMPercentage=70 (example) or explicit -Xmx to respect cgroup limits.
FAQ 1: Do I need a JDK or a JRE for ColdFusion?
ColdFusion can run on a JRE, but a JDK is recommended. The JDK includes diagnostic tools (keytool, jcmd, jmap, jfr) that are invaluable for troubleshooting and Performance tuning. Many enterprises standardize on a JDK for servers.
FAQ 2: Will upgrading the JVM break my IIS/Apache connector?
Normally no. The wsconfig/IIS or Apache connector is independent of the JVM path. However, always restart both ColdFusion and the web server, then validate routes. If you reinstall ColdFusion or change instance names, you may need to re-run wsconfig.
FAQ 3: Which garbage collector should I use?
For Java 11/17 with ColdFusion, G1GC is a solid default and usually delivers predictable pauses and good throughput. ZGC and Shenandoah exist on newer JDKs but may not be in your support matrix. Start with G1, measure, then iterate.
FAQ 4: What if I see “Unrecognized VM option” after the upgrade?
This typically means a removed or deprecated flag is still present (e.g., CMS GC or PermGen options). Remove or replace those flags. Check your jvm.config and ColdFusion Administrator “Java and JVM” settings, then restart.
