28.4 CDS in Production and Performance Optimization
Deploying CDS in production environments requires careful planning, monitoring, and optimization strategies to maximize benefits.
Production Deployment Strategies
// Production CDS Deployment
public class ProductionDeployment {
public static void printDeploymentStrategies() {
System.out.println("=== PRODUCTION DEPLOYMENT STRATEGIES ===");
System.out.println("\n--- CONTAINERIZED DEPLOYMENTS ---");
System.out.println("\nDocker Strategy 1 - Archive in image:");
System.out.println(" FROM openjdk:17-slim AS builder");
System.out.println(" WORKDIR /build");
System.out.println(" ");
System.out.println(" # Copy application");
System.out.println(" COPY app.jar .");
System.out.println(" COPY lib/ ./lib/");
System.out.println(" ");
System.out.println(" # Create CDS archive");
System.out.println(" RUN java -XX:ArchiveClassesAtExit=app.jsa \\");
System.out.println(" -jar app.jar --warmup-and-exit");
System.out.println(" ");
System.out.println(" # Production stage");
System.out.println(" FROM openjdk:17-slim");
System.out.println(" WORKDIR /app");
System.out.println(" ");
System.out.println(" # Copy application and archive");
System.out.println(" COPY --from=builder /build/app.jar .");
System.out.println(" COPY --from=builder /build/lib/ ./lib/");
System.out.println(" COPY --from=builder /build/app.jsa .");
System.out.println(" ");
System.out.println(" # Run with CDS");
System.out.println(" CMD [\"java\", \\");
System.out.println(" \"-XX:SharedArchiveFile=/app/app.jsa\", \\");
System.out.println(" \"-Xshare:on\", \\");
System.out.println(" \"-jar\", \"app.jar\"]");
System.out.println("\nBenefits:");
System.out.println(" ✓ Archive baked into image");
System.out.println(" ✓ Consistent across containers");
System.out.println(" ✓ No runtime generation");
System.out.println(" ✓ Fastest container startup");
System.out.println("\n--- KUBERNETES DEPLOYMENT ---");
System.out.println("\nDeployment YAML:");
System.out.println(" apiVersion: apps/v1");
System.out.println(" kind: Deployment");
System.out.println(" metadata:");
System.out.println(" name: myapp");
System.out.println(" spec:");
System.out.println(" replicas: 10 # Multiple instances benefit most");
System.out.println(" template:");
System.out.println(" spec:");
System.out.println(" containers:");
System.out.println(" - name: myapp");
System.out.println(" image: myapp:1.0.0-cds");
System.out.println(" env:");
System.out.println(" - name: JAVA_OPTS");
System.out.println(" value: >");
System.out.println(" -XX:SharedArchiveFile=/app/app.jsa");
System.out.println(" -Xshare:on");
System.out.println(" -Xlog:cds=info");
System.out.println(" resources:");
System.out.println(" requests:");
System.out.println(" memory: \"512Mi\" # Reduced due to CDS");
System.out.println(" cpu: \"500m\"");
System.out.println(" readinessProbe:");
System.out.println(" httpGet:");
System.out.println(" path: /health");
System.out.println(" port: 8080");
System.out.println(" initialDelaySeconds: 10 # Faster startup");
System.out.println("\n--- MICROSERVICES ARCHITECTURE ---");
System.out.println("\nShared base layer strategy:");
System.out.println(" ");
System.out.println(" 1. Create framework archive (Spring Boot):");
System.out.println(" framework.jsa");
System.out.println(" • Spring Framework");
System.out.println(" • Spring Boot");
System.out.println(" • Common libraries");
System.out.println(" • Size: ~60MB");
System.out.println(" ");
System.out.println(" 2. Share across services:");
System.out.println(" service-a: framework.jsa + service-a.jsa (5MB)");
System.out.println(" service-b: framework.jsa + service-b.jsa (4MB)");
System.out.println(" service-c: framework.jsa + service-c.jsa (6MB)");
System.out.println(" ");
System.out.println(" 3. Memory savings:");
System.out.println(" Without CDS: 3 services × 80MB = 240MB");
System.out.println(" With CDS: 60MB shared + (5+4+6)MB = 75MB");
System.out.println(" Savings: 165MB (69% reduction)");
}
public static void printMonitoring() {
System.out.println("\n=== PRODUCTION MONITORING ===");
System.out.println("\n--- STARTUP TIME METRICS ---");
System.out.println("\nMeasure JVM startup:");
System.out.println(" # Add to application");
System.out.println(" public class Application {");
System.out.println(" private static final long START = ");
System.out.println(" System.currentTimeMillis();");
System.out.println(" ");
System.out.println(" public static void main(String[] args) {");
System.out.println(" SpringApplication.run(Application.class, args);");
System.out.println(" long duration = System.currentTimeMillis() - START;");
System.out.println(" System.out.println(\"Startup: \" + duration + \"ms\");");
System.out.println(" }");
System.out.println(" }");
System.out.println("\nPrometheus metrics:");
System.out.println(" # Application startup duration");
System.out.println(" application_startup_seconds{cds=\"enabled\"} 2.5");
System.out.println(" application_startup_seconds{cds=\"disabled\"} 4.2");
System.out.println("\n--- MEMORY FOOTPRINT ---");
System.out.println("\nMonitor resident memory:");
System.out.println(" # In container");
System.out.println(" kubectl top pod myapp-xyz");
System.out.println(" ");
System.out.println(" NAME CPU MEMORY");
System.out.println(" myapp-xyz 50m 420Mi # With CDS");
System.out.println(" myapp-abc 50m 512Mi # Without CDS");
System.out.println("\nJMX monitoring:");
System.out.println(" # Enable JMX");
System.out.println(" -Dcom.sun.management.jmxremote");
System.out.println(" -Dcom.sun.management.jmxremote.port=9010");
System.out.println(" -Dcom.sun.management.jmxremote.authenticate=false");
System.out.println(" -Dcom.sun.management.jmxremote.ssl=false");
System.out.println(" ");
System.out.println(" # Query memory usage");
System.out.println(" jconsole localhost:9010");
System.out.println("\n--- CDS VERIFICATION ---");
System.out.println("\nLog analysis:");
System.out.println(" # Check if CDS is active");
System.out.println(" kubectl logs myapp-xyz | grep -i cds");
System.out.println(" ");
System.out.println(" Expected:");
System.out.println(" [info][cds] Opened archive /app/app.jsa");
System.out.println(" [info][cds] Mapped 2345 classes");
System.out.println("\nStartup logs:");
System.out.println(" java -Xlog:cds=info:file=cds.log \\");
System.out.println(" -XX:SharedArchiveFile=app.jsa \\");
System.out.println(" -jar app.jar");
System.out.println("\nParse logs:");
System.out.println(" grep 'Mapped' cds.log");
System.out.println(" → Shows number of classes loaded from archive");
}
}
Performance Benchmarking
// CDS Performance Benchmarking
public class CDSBenchmarking {
public static void printBenchmarkingGuide() {
System.out.println("=== CDS PERFORMANCE BENCHMARKING ===");
System.out.println("\n--- STARTUP TIME BENCHMARK ---");
System.out.println("\nBenchmark script:");
System.out.println(" #!/bin/bash");
System.out.println(" ");
System.out.println(" # Benchmark without CDS");
System.out.println(" echo \"Without CDS:\"");
System.out.println(" for i in {1..20}; do");
System.out.println(" time java -Xshare:off \\");
System.out.println(" -jar app.jar --quick-exit");
System.out.println(" done 2>&1 | grep real | awk '{print $2}'");
System.out.println(" ");
System.out.println(" # Benchmark with CDS");
System.out.println(" echo \"With CDS:\"");
System.out.println(" for i in {1..20}; do");
System.out.println(" time java -XX:SharedArchiveFile=app.jsa \\");
System.out.println(" -Xshare:on \\");
System.out.println(" -jar app.jar --quick-exit");
System.out.println(" done 2>&1 | grep real | awk '{print $2}'");
System.out.println("\nExample results:");
System.out.println(" Without CDS: Average 3.2s (min 3.0s, max 3.5s)");
System.out.println(" With CDS: Average 2.1s (min 2.0s, max 2.3s)");
System.out.println(" Improvement: 34% faster startup");
System.out.println("\n--- MEMORY FOOTPRINT BENCHMARK ---");
System.out.println("\nMultiple instances test:");
System.out.println(" #!/bin/bash");
System.out.println(" ");
System.out.println(" # Start 10 instances");
System.out.println(" for i in {1..10}; do");
System.out.println(" java -XX:SharedArchiveFile=app.jsa \\");
System.out.println(" -Xshare:on \\");
System.out.println(" -jar app.jar --port=$((8080+i)) &");
System.out.println(" echo $! >> pids.txt");
System.out.println(" done");
System.out.println(" ");
System.out.println(" # Wait for startup");
System.out.println(" sleep 30");
System.out.println(" ");
System.out.println(" # Measure total memory");
System.out.println(" ps -o pid,rss -p $(cat pids.txt | paste -sd,)");
System.out.println("\nExample results:");
System.out.println(" Without CDS:");
System.out.println(" Per-instance: 520MB RSS");
System.out.println(" Total 10 instances: 5,200MB");
System.out.println(" Shared memory: ~400MB");
System.out.println(" Physical RAM: ~4,800MB");
System.out.println(" ");
System.out.println(" With CDS:");
System.out.println(" Per-instance: 480MB RSS");
System.out.println(" Total 10 instances: 4,800MB");
System.out.println(" Shared memory: ~800MB (CDS archive)");
System.out.println(" Physical RAM: ~4,000MB");
System.out.println(" ");
System.out.println(" Savings: 800MB (17% reduction)");
System.out.println("\n--- THROUGHPUT IMPACT ---");
System.out.println("\nLoad test with JMeter:");
System.out.println(" # Create test plan");
System.out.println(" Thread Group: 100 threads");
System.out.println(" Ramp-up: 10s");
System.out.println(" Duration: 300s");
System.out.println(" ");
System.out.println(" # Run against CDS-enabled instance");
System.out.println(" jmeter -n -t test-plan.jmx \\");
System.out.println(" -l results-cds.jtl");
System.out.println(" ");
System.out.println(" # Run against baseline");
System.out.println(" jmeter -n -t test-plan.jmx \\");
System.out.println(" -l results-baseline.jtl");
System.out.println("\nResults:");
System.out.println(" Baseline: 1,200 req/s avg, 50ms p95");
System.out.println(" With CDS: 1,220 req/s avg, 48ms p95");
System.out.println(" Impact: Minimal (within margin of error)");
System.out.println(" ");
System.out.println(" Note: CDS improves startup, not steady-state throughput");
}
public static void printRealWorldCaseStudies() {
System.out.println("\n=== REAL-WORLD CASE STUDIES ===");
System.out.println("\n--- CASE 1: MICROSERVICES PLATFORM ---");
System.out.println("\nScenario:");
System.out.println(" • 15 Spring Boot microservices");
System.out.println(" • Kubernetes deployment");
System.out.println(" • 5 replicas per service (75 pods total)");
System.out.println(" • Frequent scale-up/down");
System.out.println("\nBefore CDS:");
System.out.println(" • Startup time: 45-60s per pod");
System.out.println(" • Memory per pod: 650MB");
System.out.println(" • Total cluster memory: 48GB");
System.out.println(" • Scale-up latency: 60s");
System.out.println("\nAfter CDS (shared framework layer):");
System.out.println(" • Startup time: 25-35s per pod");
System.out.println(" • Memory per pod: 520MB");
System.out.println(" • Total cluster memory: 39GB");
System.out.println(" • Scale-up latency: 35s");
System.out.println("\nBenefits:");
System.out.println(" ✓ 42% faster startup");
System.out.println(" ✓ 20% memory reduction");
System.out.println(" ✓ 9GB cluster memory saved");
System.out.println(" ✓ Better auto-scaling responsiveness");
System.out.println("\n--- CASE 2: BATCH PROCESSING ---");
System.out.println("\nScenario:");
System.out.println(" • Data processing pipeline");
System.out.println(" • 1,000 short-lived jobs per day");
System.out.println(" • Each job runs 30-120s");
System.out.println(" • Startup overhead significant");
System.out.println("\nBefore CDS:");
System.out.println(" • Job startup: 12s");
System.out.println(" • Avg job duration: 45s total (12s + 33s work)");
System.out.println(" • Daily startup overhead: 12,000s (3.3 hours)");
System.out.println("\nAfter CDS:");
System.out.println(" • Job startup: 4s");
System.out.println(" • Avg job duration: 37s total (4s + 33s work)");
System.out.println(" • Daily startup overhead: 4,000s (1.1 hours)");
System.out.println("\nBenefits:");
System.out.println(" ✓ 67% faster startup");
System.out.println(" ✓ 18% total time reduction");
System.out.println(" ✓ 2.2 hours saved daily");
System.out.println(" ✓ Better resource utilization");
System.out.println("\n--- CASE 3: SERVERLESS FUNCTIONS ---");
System.out.println("\nScenario:");
System.out.println(" • AWS Lambda functions");
System.out.println(" • Cold start problem");
System.out.println(" • Java 17 runtime");
System.out.println(" • 1GB memory allocation");
System.out.println("\nBefore CDS:");
System.out.println(" • Cold start: 8-12s");
System.out.println(" • Warm invocation: 150ms");
System.out.println(" • Timeout issues on cold start");
System.out.println("\nAfter CDS (with custom runtime):");
System.out.println(" • Cold start: 3-5s");
System.out.println(" • Warm invocation: 150ms (unchanged)");
System.out.println(" • Fewer timeouts");
System.out.println("\nAlternative - GraalVM Native Image:");
System.out.println(" • Cold start: 0.5-1s");
System.out.println(" • Warm invocation: 120ms");
System.out.println(" • Better for serverless");
}
}
Optimization Techniques
// CDS Optimization Techniques
public class CDSOptimization {
public static void printOptimizationTechniques() {
System.out.println("=== CDS OPTIMIZATION TECHNIQUES ===");
System.out.println("\n--- ARCHIVE SIZE OPTIMIZATION ---");
System.out.println("\n1. Include only hot classes:");
System.out.println(" # Analyze class load frequency");
System.out.println(" java -Xlog:cds+load=debug \\");
System.out.println(" -jar app.jar > classes-loaded.log");
System.out.println(" ");
System.out.println(" # Count class loads");
System.out.println(" awk '{print $NF}' classes-loaded.log | \\");
System.out.println(" sort | uniq -c | sort -rn > frequency.txt");
System.out.println(" ");
System.out.println(" # Keep top 80% (Pareto principle)");
System.out.println(" head -n 1000 frequency.txt | \\");
System.out.println(" awk '{print $2}' > hot-classes.lst");
System.out.println("\n2. Exclude rarely-used classes:");
System.out.println(" # Remove test frameworks");
System.out.println(" grep -v 'org/junit' classes.lst > filtered.lst");
System.out.println(" grep -v 'org/testng' filtered.lst > final.lst");
System.out.println(" ");
System.out.println(" # Remove internal classes");
System.out.println(" grep -v 'sun/reflect' final.lst > optimized.lst");
System.out.println("\n--- LAYERING STRATEGY ---");
System.out.println("\nOptimal layering:");
System.out.println(" Layer 1 (default): JDK classes");
System.out.println(" Size: ~20MB");
System.out.println(" Updates: Never (tied to JDK)");
System.out.println(" ");
System.out.println(" Layer 2 (framework): Spring, Hibernate, etc.");
System.out.println(" Size: ~40MB");
System.out.println(" Updates: Quarterly (framework upgrades)");
System.out.println(" ");
System.out.println(" Layer 3 (app): Application classes");
System.out.println(" Size: ~8MB");
System.out.println(" Updates: Daily (code changes)");
System.out.println("\nBenefits:");
System.out.println(" ✓ Small top layer → fast regeneration");
System.out.println(" ✓ Share stable layers across services");
System.out.println(" ✓ Reduce archive generation time");
System.out.println("\n--- WARMUP OPTIMIZATION ---");
System.out.println("\nComprehensive warmup:");
System.out.println(" @Component");
System.out.println(" public class WarmupService {");
System.out.println(" @EventListener(ApplicationReadyEvent.class)");
System.out.println(" public void warmup() {");
System.out.println(" // Exercise all endpoints");
System.out.println(" restTemplate.getForEntity(\"/api/users\", ...);");
System.out.println(" restTemplate.postForEntity(\"/api/orders\", ...);");
System.out.println(" ");
System.out.println(" // Trigger lazy initialization");
System.out.println(" hibernate.getSessionFactory();");
System.out.println(" ");
System.out.println(" // Load configurations");
System.out.println(" config.getAllProperties();");
System.out.println(" }");
System.out.println(" }");
System.out.println("\n--- COMBINED OPTIMIZATIONS ---");
System.out.println("\nCDS + JVM tuning:");
System.out.println(" java -XX:SharedArchiveFile=app.jsa \\");
System.out.println(" -Xshare:on \\");
System.out.println(" -XX:+TieredCompilation \\");
System.out.println(" -XX:TieredStopAtLevel=1 \\ # Skip C2 for startup");
System.out.println(" -Xverify:none \\ # Skip verification");
System.out.println(" -XX:+UseStringDeduplication \\");
System.out.println(" -jar app.jar");
System.out.println("\nStartup optimization stack:");
System.out.println(" • CDS for class loading: -30%");
System.out.println(" • Skip verification: -10%");
System.out.println(" • C1-only compilation: -15%");
System.out.println(" • Lazy initialization: -20%");
System.out.println(" Combined: -75% startup time");
}
public static void printContinuousOptimization() {
System.out.println("\n=== CONTINUOUS OPTIMIZATION ===");
System.out.println("\n--- MONITORING LOOP ---");
System.out.println("\n1. Measure baseline:");
System.out.println(" • Current startup time");
System.out.println(" • Current memory usage");
System.out.println(" • Archive size");
System.out.println("\n2. Profile class loading:");
System.out.println(" • Which classes are loaded?");
System.out.println(" • When are they loaded?");
System.out.println(" • How frequently?");
System.out.println("\n3. Optimize archive:");
System.out.println(" • Update class list");
System.out.println(" • Regenerate archive");
System.out.println(" • Test changes");
System.out.println("\n4. Deploy and verify:");
System.out.println(" • Gradual rollout");
System.out.println(" • Monitor metrics");
System.out.println(" • Compare to baseline");
System.out.println("\n5. Iterate:");
System.out.println(" • Quarterly review");
System.out.println(" • After major updates");
System.out.println(" • When performance degrades");
}
}
Troubleshooting Production Issues
// Production Troubleshooting
public class ProductionTroubleshooting {
public static void printTroubleshooting() {
System.out.println("=== PRODUCTION TROUBLESHOOTING ===");
System.out.println("\n--- ISSUE 1: NO PERFORMANCE IMPROVEMENT ---");
System.out.println("\nSymptoms:");
System.out.println(" • CDS enabled but same startup time");
System.out.println(" • Expected improvement not realized");
System.out.println("\nDiagnosis:");
System.out.println(" # Check if archive is used");
System.out.println(" kubectl logs pod-xyz | grep -i cds");
System.out.println(" ");
System.out.println(" # Check archive coverage");
System.out.println(" java -Xlog:cds=info -jar app.jar");
System.out.println("\nCommon causes:");
System.out.println(" • Archive not loaded (classpath mismatch)");
System.out.println(" • Insufficient classes in archive");
System.out.println(" • Bottleneck elsewhere (I/O, initialization)");
System.out.println(" • Single instance (no memory benefit)");
System.out.println("\n--- ISSUE 2: ARCHIVE MISMATCH ---");
System.out.println("\nSymptoms:");
System.out.println(" • 'Unable to use shared archive' warning");
System.out.println(" • Application runs but CDS disabled");
System.out.println("\nDiagnosis:");
System.out.println(" java -Xshare:on \\ # Force failure");
System.out.println(" -Xlog:cds=debug \\");
System.out.println(" -XX:SharedArchiveFile=app.jsa \\");
System.out.println(" -jar app.jar");
System.out.println("\nSolutions:");
System.out.println(" • Regenerate archive for current JDK");
System.out.println(" • Match compressed oops setting");
System.out.println(" • Verify classpath matches");
System.out.println(" • Check JVM flags match dump");
System.out.println("\n--- ISSUE 3: MEMORY NOT SHARED ---");
System.out.println("\nSymptoms:");
System.out.println(" • Multiple instances use same memory");
System.out.println(" • Expected memory savings not realized");
System.out.println("\nDiagnosis:");
System.out.println(" # Check shared memory on Linux");
System.out.println(" pmap -x $(pidof java) | grep app.jsa");
System.out.println(" ");
System.out.println(" # Look for shared vs private pages");
System.out.println(" cat /proc/$(pidof java)/smaps | \\");
System.out.println(" grep -A 15 app.jsa");
System.out.println("\nCommon causes:");
System.out.println(" • Copy-on-write triggered (pages modified)");
System.out.println(" • Different container namespaces");
System.out.println(" • Archive copied per container");
System.out.println(" • Host FS not shared");
System.out.println("\n--- ISSUE 4: SLOW ARCHIVE CREATION ---");
System.out.println("\nSymptoms:");
System.out.println(" • Archive dump takes >5 minutes");
System.out.println(" • CI/CD pipeline slowed");
System.out.println("\nSolutions:");
System.out.println(" • Reduce class list size");
System.out.println(" • Use layered archives (regenerate top only)");
System.out.println(" • Cache framework layer");
System.out.println(" • Parallelize multi-service builds");
}
}
Best Practices Checklist
// Production Best Practices
public class ProductionBestPractices {
public static void printChecklist() {
System.out.println("=== PRODUCTION BEST PRACTICES ===");
System.out.println("\n--- DEPLOYMENT ---");
System.out.println("☐ Archive baked into container image");
System.out.println("☐ Archive versioned with application");
System.out.println("☐ Automated regeneration in CI/CD");
System.out.println("☐ Separate archives per environment (dev/prod)");
System.out.println("☐ Layered archives for microservices");
System.out.println("\n--- VERIFICATION ---");
System.out.println("☐ Test with -Xshare:on in staging");
System.out.println("☐ Verify startup time improvement");
System.out.println("☐ Confirm memory savings (multiple instances)");
System.out.println("☐ Check logs for CDS activation");
System.out.println("☐ Benchmark before/after");
System.out.println("\n--- MONITORING ---");
System.out.println("☐ Track startup time metrics");
System.out.println("☐ Monitor memory footprint");
System.out.println("☐ Alert on CDS failures");
System.out.println("☐ Log archive usage");
System.out.println("☐ Regular performance reviews");
System.out.println("\n--- MAINTENANCE ---");
System.out.println("☐ Regenerate on JDK updates");
System.out.println("☐ Regenerate on dependency changes");
System.out.println("☐ Document archive creation process");
System.out.println("☐ Keep class lists in version control");
System.out.println("☐ Archive rotation strategy");
System.out.println("\n--- OPTIMIZATION ---");
System.out.println("☐ Profile class loading patterns");
System.out.println("☐ Include only frequently-used classes");
System.out.println("☐ Use layered archives for reusability");
System.out.println("☐ Combine with other optimizations");
System.out.println("☐ Continuous benchmarking");
}
}
Best Practices
- Bake archives into images: Pre-generate during container build.
- Monitor startup time: Track metrics to validate improvements.
- Use layered archives: Share framework layer across microservices.
- Automate regeneration: Include in CI/CD pipeline.
- Test thoroughly: Verify with -Xshare:on before production.
- Benchmark regularly: Ensure continued benefits as code evolves.
- Plan for multiple instances: CDS memory benefits require >1 JVM.
- Version archives properly: Tie to application and JDK version.
- Document processes: Ensure team understands CDS setup.
- Combine optimizations: CDS + lazy init + C1-only for maximum startup speed.