-XX:EliyaProfile=Production

Default value: None. Scope: product flag. Location: src/hotspot/share/runtime/globals.hpp.

When EliyaProfile=None (the default), Eliya behaves identically to upstream OpenJDK 25 with no defaults applied. When EliyaProfile=Production, Eliya activates six operational-readiness ergonomics (Phase 1, shipped 25.0.3): heap-dump-on-OOM with structured path, exit-on-OOM, Native Memory Tracking summary, predictable crash log path, container support reinforced, and diagnostic VM options unlocked. Every individual setting is applied via FLAG_SET_ERGO, so explicit command-line overrides always win.

Continuous JFR + unified GC logging are planned for Phase 2 alongside bundled local diagnostic tooling (Eclipse MAT headless, async-profiler), the FIPS variant, macOS aarch64, and TCK + AQAvit quality-signal alignment. Phase 3 adds Asymm Forensics (cross-artefact correlation) and Windows x64. Phase 4 (demand-gated) adds compliance-aligned profile values (PCIDSS, HIPAA, SOX, FedRAMP, GDPR, ISO27001, SOC2; see Available profile values below for the full Phase-4 namespace).

What this flag deliberately does not set: GC choice, GC tuning parameters (MaxGCPauseMillis, region size, IHOP), string deduplication, tiered compilation, compressed oops. JDK 25's automatic ergonomics handle GC selection better than a distribution can guess; setting opinionated GC defaults helps some workloads and hurts others.

What it sets: Phase 1 (shipped 25.0.3)

Capability Setting Purpose
Heap dump on OOM -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path> Capture the heap at the moment of failure, with predictable file location for triage
Exit on OOM -XX:+ExitOnOutOfMemoryError Fail fast on OOM: let orchestration restart the container; don't run a degraded JVM
Native Memory Tracking -XX:NativeMemoryTracking=summary Low-overhead native-memory accounting for diagnosing leak suspects in JNI / native libs / metaspace
Crash log path -XX:ErrorFile=<path>/hs_err_pid%p.log Predictable path for crash artifacts; integrates with standard triage flow
Container awareness -XX:+UseContainerSupport Honour cgroup memory and CPU limits (already default since JDK 10; reinforced explicitly)
Diagnostic options unlocked -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints Required for accurate JFR execution sampling and async-profiler usage; makes JFR + async-profiler usable today via one-flag activation (-XX:StartFlightRecording=…). Safe in production with negligible overhead

What it sets: Phase 2 (planned)

Two additional ergonomics arrive in Phase 2 alongside the bundled diagnostic tools. They cannot use FLAG_SET_ERGO (the activation mechanism is not a product flag); they need JfrOptionSet / LogConfiguration hooks.

Capability Planned setting Purpose
JFR continuous recording (Phase 2) -XX:StartFlightRecording=settings=default,disk=true,maxage=24h,maxsize=250m,dumponexit=true,filename=<path> 24-hour rolling buffer at sub-1% overhead: last day of execution profile already on disk when failure happens, dumped on JVM exit. Today: opt-in via the same flag (the unlocked diagnostic options make it usable)
Unified GC logging (Phase 2) -Xlog:gc*:file=<path>:time,uptime,level,tags:filecount=10,filesize=100m Continuous GC log with rotation. Audit-grade record of pause behaviour. Today: opt-in via the same flag

Diagnostic paths: three-level layout

When EliyaProfile=Production is active, Eliya writes diagnostic artifacts to a three-level filesystem layout that gives both service grouping and per-replica attribution by default:

${ELIYA_DIAGNOSTIC_PATH}/${service_name}/${replica_name}/${category}/

Resolution components:

Component Default Resolution chain
Base path /var/log/eliya ELIYA_DIAGNOSTIC_PATH env var → platform default
Service name default ELIYA_SERVICE_NAME-Deliya.service.name=HOSTNAME → literal default
Replica name suppressed when equal to service ELIYA_REPLICA_NAME-Deliya.replica.name=HOSTNAME → suppressed if equals service
Category Eliya-controlled One of jfr, heap, crash, gc

Replica suppression. When the resolved replica name equals the resolved service name, the replica level is suppressed and paths collapse to two levels. This handles the bare-metal multi-JVM case (where HOSTNAME is the host name, identical for all services on that host) and the all-fallback case (where the service name itself fell through to HOSTNAME). Three-level paths apply when replica is genuinely distinct from service.

Effective paths by deployment topology:

Deployment Configuration Effective JFR path
Kubernetes, 1 replica ELIYA_SERVICE_NAME=billing-service (HOSTNAME = pod name) /var/log/eliya/billing-service/billing-service-7d4b9c-xk29p/jfr/
Kubernetes, 3 replicas Same as above Three subdirectories, one per pod, all under /var/log/eliya/billing-service/
Bare-metal multi-JVM ELIYA_SERVICE_NAME=billing-service (HOSTNAME=myserver01) /var/log/eliya/billing-service/jfr/ (replica suppressed)
Bare-metal single-JVM, defaults Nothing configured (HOSTNAME=myserver01) /var/log/eliya/myserver01/jfr/ (service falls through to HOSTNAME; replica suppressed)
Custom base ELIYA_DIAGNOSTIC_PATH=/data/diag, ELIYA_SERVICE_NAME=billing /data/diag/billing/<replica>/jfr/
Explicit replica ELIYA_SERVICE_NAME=billing, ELIYA_REPLICA_NAME=replica-1 /var/log/eliya/billing/replica-1/jfr/

Why three levels. The layout is filesystem-encoded compliance metadata. An auditor asking "show me all billing-service artifacts" gets a single directory tree. An engineer asking "which replica produced this dump" sees the answer in the path itself. PID-bearing filenames within each replica directory handle the rare case of multiple JVM processes within one replica (JFR auto-names recordings with PID; heap dumps include PID; GC logs use %p substitution).

The flat per-replica directory structure works cleanly with logrotate, fluentd, vector, journald, and other ops tools that walk diagnostic paths. Per-replica directories are stable for the replica's lifetime; they don't churn within a pod.

Override semantics

Any flag or option set explicitly on the command line overrides the Eliya default. Example, override one default while keeping the rest:

Uses all Eliya defaults except NativeMemoryTracking (user value detail wins over default summary).

Example, combine Eliya's observability with Generational ZGC for sub-millisecond pauses:

Use this pattern for BFSI settlement engines, telecom signalling gateways, real-time messaging, any workload requiring strict tail latency. EliyaProfile=Production doesn't pick a GC, so -XX:+UseZGC applies cleanly on top.

Example, combine Eliya's observability with Compact Object Headers:

Reduces heap by 15–22% for object-heavy workloads. Verify dependency compatibility (libraries that introspect object layout) before enabling in production.

Example, disable JFR pre-emptively for Phase-2-ready environments:

In Phase 1 today (25.0.3), JFR is not started by EliyaProfile=Production: the profile only unlocks diagnostic options so operators can start JFR via -XX:StartFlightRecording=… in a separate flag. The -XX:-FlightRecorder switch is documented here so workloads that have measured unacceptable JFR overhead (extreme allocation rates, some HFT workloads) can preemptively disable Phase-2's continuous JFR default in advance of it landing. Once Phase 2 ships, the conflict detection framework will issue a Tier 2 warning noting that the explicit -FlightRecorder overrides the profile-implied default.

Inspecting applied values

Eliya-applied flags show {ergonomic} as the origin. Explicit user flags show {command line}.

JFR (StartFlightRecording), error file (ErrorFile), and unified logging (Xlog) settings are JVM arguments rather than flags; they don't appear in PrintFlagsFinal output. Use jcmd <pid> VM.command_line to see them on a running JVM.

-XX:+EliyaConflictCheck

Default: enabled. Scope: product flag. Location: src/hotspot/share/runtime/globals.hpp.

Controls startup-time detection of flag conflicts. When enabled (the default), Eliya inspects the command line at JVM startup and responds to suspicious or invalid flag combinations with one of three tiers:

  • Silent: user explicit settings override profile-implied defaults (established Hotspot semantics; no warning issued).
  • Warning: redundant or suspicious-but-legal combinations produce a warning to stderr; JVM continues normally.
  • Fatal: incompatible combinations cause JVM startup to fail with a descriptive error message.

For the three-tier framework, conflict examples, and rationale, see flag architecture: conflict detection.

When to disable:

Use -XX:-EliyaConflictCheck only when experimenting with flag combinations or running CI matrix tests where intentional invalid combinations are part of the test plan. Production deployments should leave conflict checking enabled; fail-fast on misconfiguration is the right operational posture.

Available profile values

Profile value Phase Effect
None Phase 1 Default: no Eliya-specific defaults applied; equivalent to upstream OpenJDK 25
Production Phase 1 Production-readiness profile (documented above)
PCIDSS, HIPAA, SOX, FedRAMP, GDPR, ISO27001, SOC2 Phase 4 (reserved) Single-framework compliance profiles; demand-gated
Combined profiles (e.g., Healthcare-Payment, Financial-SaaS, Federal-Defense) Phase 4 (reserved) Explicit unions of compliance frameworks for industries needing multiple, designed when customer demand justifies; never stacked from individual profiles

For the full Phase 1 surface and Phase 2/4 roadmap, see flag architecture.

Performance impact

The observability defaults activated by -XX:EliyaProfile=Production are designed for always-on production use. Empirical overhead is small but not zero; this section documents what to expect and where the trade-offs are.

Steady-state overhead by component

Component CPU overhead Memory overhead Disk overhead
JFR default profile recording (Phase 2) <1% typical, <2% worst case (default profile only; settings=profile adds more) ~8-16 MB internal buffers ~250 MB rolling (configurable)
Native Memory Tracking summary Low ~5-10 MB None
GC logging with rotation (Phase 2) Negligible None ~1 GB total (10 × 100 MB)
Heap dump on OOM Zero during normal operation Zero Triggered only on OOM
Crash log path Zero Zero Triggered only on JVM crash
Container support reinforced Zero Zero None
Diagnostic VM options unlocked Zero Zero None

The <1% JFR overhead applies to the default JFR profile that Eliya configures by default (settings=default). The profile.jfc template (deeper sampling, allocation profiling) has higher overhead and is not the Eliya default.

Combined overhead

The dominant component once continuous JFR ships in Phase 2 is JFR itself (JEP 328 positions the default profile at <1%). NMT summary mode adds a smaller amount on top (Oracle's NMT documentation cites 5-10% as a general range across modes, with summary mode at the lower end). GC logging and the unlocked diagnostic options contribute negligibly. Actual overhead varies with workload characteristics (allocation rate, GC pressure, lock contention); measure for your workload before committing to a steady-state budget.

JFR's overhead is the most-studied component and the one that historically drove operator concern. Multiple independent sources confirm sub-1% JFR overhead with the default profile:

  • Oracle benchmarks: JFR with the default profile is documented at sub-1% overhead and is designed for always-on production use (Oracle JDK Mission Control documentation).
  • JFR design intent: Marcus Hirt, the OpenJDK JDK Mission Control (JMC) project lead, has consistently positioned JFR as production-grade always-on instrumentation, including for performance-sensitive workloads.
  • Production deployments at scale: Datadog Continuous Profiler, New Relic Java Profiler, and Azure Application Insights all rely on JFR. These SaaS vendors would not have built businesses on JFR if the overhead were operationally meaningful.
  • Microsoft Azure Spring Apps (formerly Azure Spring Cloud) exposes JFR-based continuous diagnostics as a first-class platform capability.
  • Open-source maturity: JFR has been GPLv2 and publicly available since JDK 11 (JEP 328, 2018): seven years of public production hardening.

Where overhead may be higher

Two workload classes are worth measuring before committing:

  1. Extreme allocation rates (sustained >10M object allocations per second). JFR's allocation events have a per-allocation cost. The default profile samples allocations rather than recording all, which mitigates but doesn't eliminate this. Workloads near this threshold (HFT order books, certain log aggregation pipelines, in-memory analytics) should benchmark with and without -XX:EliyaProfile=Production before committing.
  2. Tight container resource budgets. JFR's internal buffers consume ~8-16 MB. On containers with <512 MB heap, this becomes proportionally larger. JFR's disk buffer (default 250 MB) needs free disk space; on containers with <500 MB available disk, buffer rotation may cause disk pressure.

What this flag does NOT cost

  • GC selection (G1 default per JDK 25 ergonomics, same as upstream)
  • GC tuning parameters (no changes to pause targets, region size, IHOP)
  • JIT compilation behaviour (same tier transitions as upstream)
  • Class loading or module system (unchanged)
  • Application throughput characteristics beyond the ~1-2% steady-state overhead

Opting out

If the trade-off doesn't fit your workload, don't set -XX:EliyaProfile=Production. Eliya without the flag is functionally identical to upstream OpenJDK 25: same source tree, same JIT, same GC, same TLS defaults, same java.security. The flag is opt-in, not coercive.

The trade-off, in plain language

Phase 1 today (25.0.3): The six operational-readiness ergonomics cost low steady-state CPU (dominated by NMT summary mode; everything else triggers only on the actual event). In exchange you have heap-dump-on-OOM landing in a predictable structured path, NMT summary visible via jcmd, the crash log where you expect it, and diagnostic options unlocked so JFR + async-profiler are one-flag-away when you need them.

Phase 2: The trade-off changes once continuous JFR + unified GC logging become defaults: an additional ~1–2% steady-state CPU overhead, in exchange for 24 hours of execution profile data already on disk when an incident occurs.

The Phase 2 economics: 1.5% CPU overhead on a 2 vCPU container at typical cloud pricing (~$50/month) costs roughly $0.75/month per replica. A single major incident diagnosed without forensic data typically consumes 8–40 engineering hours at $200/hr: $1,600 to $8,000 per incident, plus business impact during the time-to-root-cause. One avoided incident pays for years of Phase-2 continuous observability across a sizeable fleet.

For compliance-conscious teams in regulated industries, the Phase 2 trade-off is almost always worth it; the alternative is realising you don't have observability data after the incident has already happened. For latency-sensitive workloads where every microsecond matters (HFT, low-latency messaging gateways, real-time signalling), measure before committing once Phase 2 ships.

For where Eliya's forensic posture fits alongside SaaS APM platforms, see JVM forensics vs APM. For the vendor-by-vendor JDK comparison (and why Eliya doesn't tune GC), see Choosing a JDK in 2026.

Security defaults: inherited from upstream

Eliya inherits upstream OpenJDK 25's security configuration unchanged. JDK 25 already disables SSLv3, TLS 1.0, TLS 1.1, weak ciphers (RC4, DES, MD5), and enforces NIST-aligned minimum key sizes. Eliya does not modify $JAVA_HOME/conf/security/java.security; re-declaring upstream defaults as Eliya features would add nothing.

Verify with a diff:

Full security posture on the security page. Precise diff from upstream: Differences from upstream OpenJDK 25.

Opt-out (not recommended)

The double equals == overrides; a single = appends. Only use this if a legacy integration genuinely requires TLS 1.0 or weak ciphers.

[ } Eliya Eliya Dial Dial
Privacy
[ }
[ }
// PRODUCTS Eliya Eliya Dial Dial