[{"data":1,"prerenderedAt":1477},["ShallowReactive",2],{"services":3,"service-\u002Fservices\u002Fdrift-monitoring":776,"service-articles-\u002Fservices\u002Fdrift-monitoring":825,"service-surround-\u002Fservices\u002Fdrift-monitoring":1475},[4,257,383,502,603,693],{"id":5,"title":6,"body":7,"category":238,"description":239,"engagement":240,"extension":241,"headline":242,"icon":243,"meta":244,"navigation":245,"order":246,"outcomes":247,"path":253,"seo":254,"stem":255,"__hash__":256},"services\u002Fservices\u002Fjvm-discovery.md","JVM Discovery & Estate Assessment",{"type":8,"value":9,"toc":228},"minimark",[10,15,24,27,31,34,79,83,93,125,129,206,210],[11,12,14],"h2",{"id":13},"the-problem","The problem",[16,17,18,19,23],"p",{},"Most enterprises can't produce an accurate, current list of the Java runtimes they run. The CMDB records some. Config management records others. The rest are ",[20,21,22],"strong",{},"shadow JVMs",": runtimes bundled inside vendor products, application servers, CI\u002FCD agents, monitoring tools, desktop software and container images that nobody thinks of as \"Java\".",[16,25,26],{},"Shadow JVMs are the ones that miss every patch cycle. For Oracle Java, they are also the installs that can put your entire headcount in scope for a subscription.",[11,28,30],{"id":29},"what-we-find","What we find",[16,32,33],{},"For every JVM across dev, staging and production we capture:",[35,36,37,44,50,56,62,68],"ul",{},[38,39,40,43],"li",{},[20,41,42],{},"Version, vendor and patch level",": Oracle JDK, Eclipse Temurin, Amazon Corretto, Azul Zulu, Red Hat, Microsoft, IBM Semeru and others",[38,45,46,49],{},[20,47,48],{},"Where it is embedded",": standalone apps, Tomcat, WebLogic, WebSphere, JBoss\u002FWildFly, vendor products, containers",[38,51,52,55],{},[20,53,54],{},"CVE exposure",", mapped to each version and scored so the worst exposure rises to the top",[38,57,58,61],{},[20,59,60],{},"Installed agents",": APM, security and profiling agents, which cause many patch failures",[38,63,64,67],{},[20,65,66],{},"Ownership",": who actually runs each application. This is often the hardest part to get right.",[38,69,70,73,74],{},[20,71,72],{},"Criticality signals"," that feed ",[75,76,78],"a",{"href":77},"\u002Fapproach#classification","application classification",[11,80,82],{"id":81},"how-we-do-it","How we do it",[84,85,86],"note",{},[16,87,88,89,92],{},"Discovery is ",[20,90,91],{},"read-only",". Nothing is patched, restarted or deployed, so the engagement doesn't need change-control approval, and the access we ask for is kept to a minimum.",[35,94,95,101,107,113,119],{},[38,96,97,100],{},[20,98,99],{},"Agentless scanning"," over SSH and WinRM (process listings and filesystem inspection) where possible",[38,102,103,106],{},[20,104,105],{},"Reconciliation against your CMDB and config management"," (Ansible, Puppet, Chef). The drift between what is recorded and what is running is a finding in its own right.",[38,108,109,112],{},[20,110,111],{},"Cloud provider APIs"," (AWS, Azure, GCP) for instance and container metadata",[38,114,115,118],{},[20,116,117],{},"Container image and artifact repository scanning"," (registries, Nexus, Artifactory) to catch JVMs before they are even running",[38,120,121,124],{},[20,122,123],{},"Reuse of the scanners you already own",". Tenable, Qualys, Snyk and JFrog Xray already collect useful data. We add the JVM-specific interpretation and a remediation plan; we don't sell you another scanner.",[11,126,128],{"id":127},"three-ways-to-engage","Three ways to engage",[130,131,132,151],"table",{},[133,134,135],"thead",{},[136,137,138,142,145,148],"tr",{},[139,140,141],"th",{},"Package",[139,143,144],{},"Scope",[139,146,147],{},"Turnaround",[139,149,150],{},"Purpose",[152,153,154,171,187],"tbody",{},[136,155,156,162,165,168],{},[157,158,159],"td",{},[20,160,161],{},"Quick Scan",[157,163,164],{},"One business unit or subset of the estate",[157,166,167],{},"Days",[157,169,170],{},"Prove what a full assessment will find",[136,172,173,178,181,184],{},[157,174,175],{},[20,176,177],{},"Full Estate Assessment",[157,179,180],{},"The whole estate",[157,182,183],{},"2–4 weeks",[157,185,186],{},"Complete inventory, risk report and remediation plan",[136,188,189,197,200,203],{},[157,190,191],{},[20,192,193],{},[75,194,196],{"href":195},"\u002Fservices\u002Fdrift-monitoring","Continuous Drift Monitoring",[157,198,199],{},"Ongoing",[157,201,202],{},"Subscription",[157,204,205],{},"Keep the inventory, risk and license picture current",[11,207,209],{"id":208},"what-you-walk-away-with","What you walk away with",[16,211,212,213,217,218,222,223,227],{},"The executive summary puts the findings in business terms: unbudgeted license exposure, days of exposure on unpatched critical CVEs, and the percentage of the estate on end-of-life versions. It ends with a direct recommendation of which applications belong in ",[75,214,216],{"href":215},"\u002Fservices\u002Frapid-patch","Rapid Patch",", which need ",[75,219,221],{"href":220},"\u002Fservices\u002Fcritical-patch-assurance","Critical Patch Assurance",", and which Oracle installs to ",[75,224,226],{"href":225},"\u002Fservices\u002Fopenjdk-migration","migrate or keep",".",{"title":229,"searchDepth":230,"depth":231,"links":232},"",2,3,[233,234,235,236,237],{"id":13,"depth":230,"text":14},{"id":29,"depth":230,"text":30},{"id":81,"depth":230,"text":82},{"id":127,"depth":230,"text":128},{"id":208,"depth":230,"text":209},"jvm-discovery","Find every JVM in your estate, including the ones bundled inside vendor products and containers, and turn the findings into a prioritized, costed remediation plan.","Read-only and fixed-price. A Quick Scan of one business unit takes days; a Full Estate Assessment takes two to four weeks. Nothing changes in production, so no CAB approval is needed.","md","Start here","i-lucide-radar",{},true,1,[248,249,250,251,252],"A complete inventory of every JVM, with version, vendor, patch level and location","CVE exposure scored per JVM, not a raw vulnerability count","Oracle Java license exposure quantified in dollars","Owners mapped for each application","An executive summary with a prioritized remediation plan","\u002Fservices\u002Fjvm-discovery",{"title":6,"description":239},"services\u002Fjvm-discovery","xwCt4w5iuENInyc5KpzKLmV4sk8GzNe5e1H4Q9b7mV8",{"id":258,"title":259,"body":260,"category":368,"description":369,"engagement":370,"extension":241,"headline":371,"icon":372,"meta":373,"navigation":245,"order":230,"outcomes":374,"path":225,"seo":380,"stem":381,"__hash__":382},"services\u002Fservices\u002Fopenjdk-migration.md","Oracle Java Licensing & OpenJDK Migration",{"type":8,"value":261,"toc":358},[262,266,273,279,287,293,297,302,309,313,316,320,323,327,335,339],[11,263,265],{"id":264},"why-this-is-urgent","Why this is urgent",[16,267,268,269,272],{},"Since January 2023, Oracle has sold Java SE through the ",[20,270,271],{},"Java SE Universal Subscription",", which is priced per employee rather than per installation. The count covers full-time, part-time and temporary staff, plus contractors who support internal operations, however few machines actually run Oracle Java.",[16,274,275,276,227],{},"So a handful of forgotten Oracle JDK installs can put your whole headcount in scope. For example, an organization of 5,000 employees running Oracle Java on 40 servers can face a list-price bill of around ",[20,277,278],{},"$630,000 a year",[16,280,281,282,286],{},"The free window is closing too. Oracle's No-Fee Terms and Conditions (NFTC) cover each LTS release only until one year after the next LTS ships. For Oracle JDK 21, that window ",[75,283,285],{"href":284},"\u002Farticles\u002Fjava-21-nftc-free-period-ended","closed on September 16, 2026",". Continuing to patch it now requires a paid subscription.",[288,289,290],"warning",{},[16,291,292],{},"We are not lawyers, and nothing here is legal advice. Licensing terms and prices change; check them against Oracle's current price list and your own agreements. Where a formal licensing position is needed, we work alongside independent licensing specialists.",[11,294,296],{"id":295},"what-we-do","What we do",[298,299,301],"h3",{"id":300},"_1-quantify-the-exposure","1. Quantify the exposure",[16,303,304,305,308],{},"Using the ",[75,306,307],{"href":253},"discovery inventory",", we identify every Oracle JDK and JRE, how it got there, and whether it is covered by another product's license. Then we put a number on what it costs you.",[298,310,312],{"id":311},"_2-decide-install-by-install","2. Decide, install by install",[16,314,315],{},"Most Oracle installs have no reason to be Oracle. A few do: vendor certification requirements or specific support needs. We make that call explicitly for each install instead of by default.",[298,317,319],{"id":318},"_3-migrate","3. Migrate",[16,321,322],{},"OpenJDK builds from Eclipse Adoptium (Temurin), Amazon (Corretto), Azul (Zulu), Red Hat and Microsoft are TCK-tested and free to use in production. For same-version swaps, migration is usually low risk, but not zero risk. We check for the known differences: truststore contents, installer paths and registry keys, fonts, and old commercial-feature flags. Then we roll out progressively.",[298,324,326],{"id":325},"_4-prove-it","4. Prove it",[16,328,329,330,334],{},"Uninstalling is not the same as re-pointing ",[331,332,333],"code",{},"JAVA_HOME",". We verify that Oracle binaries are actually gone and keep the evidence, which you will want if Oracle ever asks.",[11,336,338],{"id":337},"further-reading","Further reading",[35,340,341,346,352],{},[38,342,343],{},[75,344,345],{"href":284},"Oracle JDK 21's free update window has closed",[38,347,348],{},[75,349,351],{"href":350},"\u002Farticles\u002Foracle-java-employee-metric-explained","Oracle's employee-based Java pricing, explained",[38,353,354],{},[75,355,357],{"href":356},"\u002Farticles\u002Foracle-jdk-to-openjdk-migration-checklist","An Oracle JDK to OpenJDK migration checklist",{"title":229,"searchDepth":230,"depth":231,"links":359},[360,361,367],{"id":264,"depth":230,"text":265},{"id":295,"depth":230,"text":296,"children":362},[363,364,365,366],{"id":300,"depth":231,"text":301},{"id":311,"depth":231,"text":312},{"id":318,"depth":231,"text":319},{"id":325,"depth":231,"text":326},{"id":337,"depth":230,"text":338},"oracle-licensing","Quantify your Oracle Java SE exposure, then move every install that doesn't need Oracle onto a free, drop-in OpenJDK build, with evidence you can take to an audit or renewal.","Fixed-scope. We start from the discovery inventory, size your exposure, then migrate in waves. Low-criticality apps go first via Rapid Patch.","Often pays for itself","i-lucide-arrow-right-left",{},[375,376,377,378,379],"Your Oracle Java license exposure, in dollars, with the installs that drive it","A keep-or-migrate decision for every Oracle JDK install","Migration to Temurin, Corretto, Zulu, Red Hat or Microsoft builds of OpenJDK","Verified removal of Oracle binaries, with an evidence trail","Data to negotiate from ahead of an audit or renewal",{"title":259,"description":369},"services\u002Fopenjdk-migration","0aWf4Vd_7P0phaKwOWxq3bLjO4iX8gdRjDu_tPGAWBY",{"id":384,"title":216,"body":385,"category":488,"description":489,"engagement":490,"extension":241,"headline":491,"icon":492,"meta":493,"navigation":245,"order":231,"outcomes":494,"path":215,"seo":499,"stem":500,"__hash__":501},"services\u002Fservices\u002Frapid-patch.md",{"type":8,"value":386,"toc":482},[387,391,394,401,405,412,424,428,465,471,475],[11,388,390],{"id":389},"the-premise","The premise",[16,392,393],{},"Full regression testing before every JVM security patch is the main reason enterprise patch cycles take months. For business-critical systems that rigor is warranted. For the long tail of internal tools, batch jobs and low-traffic services it usually isn't. There it just delays the fix for a known CVE.",[16,395,396,397,400],{},"Rapid Patch ",[20,398,399],{},"does not skip testing",". It replaces pre-deployment regression testing with fast detection and fast rollback. If a bad patch is caught in minutes and reversed in minutes, running without an exhaustive test suite costs very little.",[11,402,404],{"id":403},"who-its-for","Who it's for",[16,406,407,408,411],{},"Applications that score below the critical threshold in our ",[75,409,410],{"href":77},"classification process",". This is a documented, weighted score with a named risk-acceptor, not an app owner's self-assessment. Apps near the threshold go to manual review.",[16,413,414,415,418,419,423],{},"Rapid Patch covers ",[20,416,417],{},"same-major security patches"," (for example 17.0.x to the next 17.0.x). Major version upgrades and vendor swaps are ",[75,420,422],{"href":421},"\u002Fapproach#patch-types","different engagements"," with a different risk profile.",[11,425,427],{"id":426},"how-it-works","How it works",[35,429,430,436,442,448,454],{},[38,431,432,435],{},[20,433,434],{},"Progressive rollout",": canary at 1%, then 10%, then 100%, gated on automated health checks",[38,437,438,441],{},[20,439,440],{},"Observability as the safety net",": error rates, latency, GC pause times, heap and thread behavior compared before and after the patch",[38,443,444,447],{},[20,445,446],{},"Fast, rehearsed rollback",": the previous runtime stays in place until the soak period ends, and rollback is exercised, not just written down",[38,449,450,453],{},[20,451,452],{},"Smoke tests and synthetic transactions"," for the paths that matter, in place of a full regression suite",[38,455,456,459,460,464],{},[20,457,458],{},"A pre-flight check"," for ",[75,461,463],{"href":462},"\u002Farticles\u002Fjvm-patch-failure-modes","known failure modes",": APM agents, TLS defaults, GC flags",[466,467,468],"tip",{},[16,469,470],{},"In many non-containerized estates, reliable rollback is the real gap. When that's the case we fix it first, because that step alone makes the patch cycle faster.",[11,472,474],{"id":473},"governance","Governance",[16,476,477,478],{},"Your Change Advisory Board approves the process once, as a standard change for a defined tier, instead of approving each patch. Every rollout produces evidence: which signals were checked, the results, timestamps, and who accepted the risk. ",[75,479,481],{"href":480},"\u002Farticles\u002Fcab-approval-for-faster-jvm-patching","How we get this past a CAB →",{"title":229,"searchDepth":230,"depth":231,"links":483},[484,485,486,487],{"id":389,"depth":230,"text":390},{"id":403,"depth":230,"text":404},{"id":426,"depth":230,"text":427},{"id":473,"depth":230,"text":474},"patch-management","Patch the long tail of non-business-critical Java apps in days, not quarters, by replacing full regression testing with progressive rollout, fast detection and rehearsed rollback.","Fixed-scope rollout of a patching pipeline and governance model for a defined tier of applications, followed by patch cycles run each quarter.","For non-critical apps","i-lucide-zap",{},[495,496,497,498],"Security patches applied across the tier in days after each quarterly release","Progressive rollout with automated health gates","A rollback path that has been tested, not just documented","A CAB-approved standard-change process and audit trail",{"title":216,"description":489},"services\u002Frapid-patch","qDIP1lgG0nnDOEyokq47L3LSfKbmYPHSlBnCXM3udLw",{"id":503,"title":221,"body":504,"category":588,"description":589,"engagement":590,"extension":241,"headline":591,"icon":592,"meta":593,"navigation":245,"order":594,"outcomes":595,"path":220,"seo":600,"stem":601,"__hash__":602},"services\u002Fservices\u002Fcritical-patch-assurance.md",{"type":8,"value":505,"toc":576},[506,510,517,523,527,531,534,538,541,545,548,552,555,559,562,566,569,573],[11,507,509],{"id":508},"a-different-promise","A different promise",[16,511,512,513,516],{},"For business-critical applications the value proposition flips. We aren't removing testing. We ",[20,514,515],{},"compress"," it so that each test cycle is shorter and gives you more confidence, and full rigor becomes possible on a faster cadence.",[16,518,519,520,522],{},"This is a different engagement from ",[75,521,216],{"href":215},", built on a different premise, not the same thing done more carefully.",[11,524,526],{"id":525},"whats-in-it","What's in it",[298,528,530],{"id":529},"test-impact-analysis-and-risk-based-test-selection","Test impact analysis and risk-based test selection",[16,532,533],{},"We use code coverage and change-impact analysis to find which of your existing regression tests actually exercise code paths affected by the JVM change, and run those on a compressed timeline. When the signal is ambiguous we escalate to the full suite.",[298,535,537],{"id":536},"shadow-traffic-and-dark-launch-testing","Shadow traffic and dark launch testing",[16,539,540],{},"We mirror real production traffic to a shadow instance running the patched JVM and diff its outputs against production, with no user exposure. This is the strongest \"test better, not less\" option available for critical services.",[298,542,544],{"id":543},"upgrade-readiness-assessment","Upgrade readiness assessment",[16,546,547],{},"Before any patch or upgrade, we scan for removed and deprecated API usage, known agent incompatibilities and dependency issues, and produce a risk report up front.",[298,549,551],{"id":550},"staging-and-production-parity-audits","Staging and production parity audits",[16,553,554],{},"Much critical-app patch risk comes from drift between staging and production, not from the patch itself. Closing that gap often gives you more than adding tests does.",[298,556,558],{"id":557},"canary-gates-on-business-metrics","Canary gates on business metrics",[16,560,561],{},"We go beyond latency and error rates to business invariants, such as transaction success rate, order completion and revenue per minute, and use them as automated rollback triggers.",[298,563,565],{"id":564},"patch-trains-and-war-room-support","Patch trains and war-room support",[16,567,568],{},"Scheduled, batched patch windows for critical apps, with dedicated live support during rollout, instead of ad hoc patching.",[298,570,572],{"id":571},"lts-aligned-strategy-and-vendor-coordination","LTS-aligned strategy and vendor coordination",[16,574,575],{},"Critical apps stay on designated LTS and security baselines, which keeps exposure windows short without constant churn. Where it matters, we work directly with your JVM vendor on compatibility and support commitments.",{"title":229,"searchDepth":230,"depth":231,"links":577},[578,579],{"id":508,"depth":230,"text":509},{"id":525,"depth":230,"text":526,"children":580},[581,582,583,584,585,586,587],{"id":529,"depth":231,"text":530},{"id":536,"depth":231,"text":537},{"id":543,"depth":231,"text":544},{"id":550,"depth":231,"text":551},{"id":557,"depth":231,"text":558},{"id":564,"depth":231,"text":565},{"id":571,"depth":231,"text":572},"risk-governance","For business-critical Java applications, we compress testing instead of removing it, so full rigor fits a faster patch cadence.","A higher-touch engagement for critical applications, typically starting with an upgrade-readiness assessment and continuing with scheduled patch trains.","For the apps that run the business","i-lucide-shield",{},4,[596,597,598,599],"Shorter test cycles for critical apps with the same or greater confidence","Shadow-traffic validation with no user exposure","Canary gates on business metrics, not just infrastructure metrics","Scheduled patch trains with live war-room support",{"title":221,"description":589},"services\u002Fcritical-patch-assurance","utoXA8F7946svO9yfDqjkPV5VtPJhDVhuelRoxSfZeU",{"id":604,"title":605,"body":606,"category":676,"description":677,"engagement":678,"extension":241,"headline":679,"icon":680,"meta":681,"navigation":245,"order":682,"outcomes":683,"path":689,"seo":690,"stem":691,"__hash__":692},"services\u002Fservices\u002Fthird-party-applications.md","Vendor & Third-Party Application JVMs",{"type":8,"value":607,"toc":672},[608,612,622,625,627,667],[11,609,611],{"id":610},"the-jvms-nobody-owns","The JVMs nobody owns",[16,613,614,615,618,619,227],{},"A large share of the Java in an enterprise wasn't written there. Application servers, database tooling, CI\u002FCD servers, monitoring agents, ETL tools, security appliances and desktop software often ship their ",[20,616,617],{},"own private JVM",", installed outside the package manager and invisible to anything that only checks the system ",[331,620,621],{},"java",[16,623,624],{},"These runtimes fall between two chairs. The platform team assumes the vendor patches them; the vendor assumes you'll apply their next release; the application owner assumes it's all fine. Meanwhile the bundled JVM ages.",[11,626,296],{"id":295},[35,628,629,639,645,655,661],{},[38,630,631,634,635,638],{},[20,632,633],{},"Find and attribute them."," ",[75,636,637],{"href":253},"Discovery"," surfaces bundled runtimes and ties each one to a product, version and business owner.",[38,640,641,644],{},[20,642,643],{},"Establish the supportability position."," For each product: does the vendor ship JVM updates, do they support replacing the bundled runtime, and which JDK builds do they certify?",[38,646,647,650,651,654],{},[20,648,649],{},"Patch what can be patched."," Through vendor updates or supported runtime swaps, rolled out with the same ",[75,652,653],{"href":215},"detection and rollback discipline"," as your own apps.",[38,656,657,660],{},[20,658,659],{},"Protect what can't."," Network isolation, disabling vulnerable features, tighter access. The compensating controls are documented so your risk register reflects reality.",[38,662,663,666],{},[20,664,665],{},"Take it to the vendor."," Certified-JDK questions, SBOM requests and patch-timeline commitments, backed by the specific evidence you need for a contract conversation.",[84,668,669],{},[16,670,671],{},"Some commercial products include a restricted Oracle Java license for use with that product only. Whether a bundled Oracle runtime creates licensing exposure depends on the product's terms, so we check them rather than assuming either way.",{"title":229,"searchDepth":230,"depth":231,"links":673},[674,675],{"id":610,"depth":230,"text":611},{"id":295,"depth":230,"text":296},"third-party-apps","Advisory for the Java you don't build yourself, including commercial products, appliances and vendor-bundled runtimes, so they get patched or protected instead of forgotten.","Advisory engagement scoped per vendor portfolio, usually following a discovery engagement that surfaces the bundled runtimes.","Second- and third-party apps","i-lucide-package",{},5,[684,685,686,687],"Every vendor-bundled JVM identified and attributed to a product and owner","A supportability position for each (vendor update, supported JRE swap or neither)","Compensating controls where patching isn't possible",{"Vendor asks backed by evidence":688},"certified JDKs, SBOMs, patch timelines","\u002Fservices\u002Fthird-party-applications",{"title":605,"description":677},"services\u002Fthird-party-applications","oy1ThKLwcn-G3Z5DaUWp8Maj1EXsbbInm5duRfzyfRs",{"id":694,"title":196,"body":695,"category":238,"description":763,"engagement":764,"extension":241,"headline":202,"icon":765,"meta":766,"navigation":245,"order":767,"outcomes":768,"path":195,"seo":773,"stem":774,"__hash__":775},"services\u002Fservices\u002Fdrift-monitoring.md",{"type":8,"value":696,"toc":758},[697,701,704,707,711,747,751],[11,698,700],{"id":699},"assessments-go-stale","Assessments go stale",[16,702,703],{},"An estate assessment is accurate the day it's delivered. After that, teams deploy new services, vendors ship updates with new bundled runtimes, someone installs Oracle JDK on a build agent, and a new CVE lands against a version you thought was fine.",[16,705,706],{},"Continuous Drift Monitoring keeps the picture current. The inventory becomes a system of record instead of a PDF.",[11,708,710],{"id":709},"what-it-watches","What it watches",[35,712,713,719,725,731,737],{},[38,714,715,718],{},[20,716,717],{},"New and undocumented JVMs"," across hosts, containers and artifact repositories",[38,720,721,724],{},[20,722,723],{},"Patch-level drift",": which runtimes fell behind after each quarterly critical patch update",[38,726,727,730],{},[20,728,729],{},"New CVEs"," against the versions and dependencies you actually run",[38,732,733,736],{},[20,734,735],{},"License exposure changes",": a new Oracle JDK install is flagged before it shows up in an audit",[38,738,739,742,743,746],{},[20,740,741],{},"Classification triggers",", such as a new regulated data flow, a traffic spike or an incident, which force an application's ",[75,744,745],{"href":77},"risk tier"," to be re-scored",[11,748,750],{"id":749},"how-its-delivered","How it's delivered",[16,752,753,754,757],{},"Collection reuses the minimum-privilege methods from the ",[75,755,756],{"href":253},"original assessment",". Findings go to a shared dashboard and to the channels your teams already use. Each quarter, aligned to the Java patch calendar, we review drift, exposure and upcoming end-of-life dates with you.",{"title":229,"searchDepth":230,"depth":231,"links":759},[760,761,762],{"id":699,"depth":230,"text":700},{"id":709,"depth":230,"text":710},{"id":749,"depth":230,"text":750},"Keep your JVM inventory, patch posture and Oracle license exposure current as the estate changes, instead of commissioning a new assessment every year.","Ongoing subscription after an estate assessment. Continuous collection, alerting on meaningful changes, and a quarterly review aligned to the Java patch calendar.","i-lucide-refresh-cw",{},6,[769,770,771,772],"New and undocumented JVMs detected as they appear","Patch-level drift tracked against each quarterly release","Alerts when a new install creates Oracle license exposure","Automatic re-classification when an app's risk profile changes",{"title":196,"description":763},"services\u002Fdrift-monitoring","Phmhi-GcB9IZ5dN4HFjsW_dg9QF_D9rXUNzILnRNAKE",{"id":694,"title":196,"body":777,"category":238,"description":763,"engagement":764,"extension":241,"headline":202,"icon":765,"meta":822,"navigation":245,"order":767,"outcomes":823,"path":195,"seo":824,"stem":774,"__hash__":775},{"type":8,"value":778,"toc":817},[779,781,783,785,787,811,813],[11,780,700],{"id":699},[16,782,703],{},[16,784,706],{},[11,786,710],{"id":709},[35,788,789,793,797,801,805],{},[38,790,791,718],{},[20,792,717],{},[38,794,795,724],{},[20,796,723],{},[38,798,799,730],{},[20,800,729],{},[38,802,803,736],{},[20,804,735],{},[38,806,807,742,809,746],{},[20,808,741],{},[75,810,745],{"href":77},[11,812,750],{"id":749},[16,814,753,815,757],{},[75,816,756],{"href":253},{"title":229,"searchDepth":230,"depth":231,"links":818},[819,820,821],{"id":699,"depth":230,"text":700},{"id":709,"depth":230,"text":710},{"id":749,"depth":230,"text":750},{},[769,770,771,772],{"title":196,"description":763},[826],{"id":827,"title":828,"author":829,"body":830,"category":238,"date":1460,"description":1461,"draft":1462,"extension":241,"featured":1462,"image":1463,"meta":1464,"navigation":245,"path":1465,"readingTime":767,"seo":1466,"stem":1467,"tags":1468,"updated":1463,"__hash__":1474},"articles\u002Farticles\u002Ffinding-every-jvm-in-your-estate.md","You can't patch what you can't find: building a real JVM inventory","patchmageddon-team",{"type":8,"value":831,"toc":1436},[832,835,838,842,845,849,856,863,867,870,874,881,885,888,892,895,967,975,979,982,986,989,1007,1010,1294,1304,1309,1313,1316,1319,1322,1326,1329,1333,1336,1340,1343,1347,1354,1384,1387,1391,1395,1398,1402,1405,1409,1412,1417,1421,1432],[16,833,834],{},"Ask a platform team how many Java runtimes the company runs and you'll usually get a confident number. Ask where that number came from and the confidence drops. It's typically the CMDB, a vulnerability scanner report, or a spreadsheet someone built during the last Log4j scramble.",[16,836,837],{},"None of those is wrong, exactly. They're incomplete in ways nobody can measure. That's the problem, because every later step (patching, upgrades, license decisions, audit responses) depends on the list being right.",[11,839,841],{"id":840},"why-nobody-has-an-accurate-list","Why nobody has an accurate list",[16,843,844],{},"JVMs don't only show up as \"a Java application we deployed.\" They arrive in several other ways, and most of those skip the processes that would record them.",[298,846,848],{"id":847},"shadow-jvms-inside-vendor-products","Shadow JVMs inside vendor products",[16,850,851,852,855],{},"Commercial software often ships its own private Java runtime. Databases, monitoring tools, backup agents, BI platforms, network management consoles and security products regularly bundle a JRE in their install directory. It isn't on the ",[331,853,854],{},"PATH",", it doesn't show up in the OS package manager, and the team that installed the product often doesn't know it's there.",[16,857,858,859,227],{},"These runtimes tend to be the oldest in the estate, because they're only updated when the vendor ships a new release. We cover how to handle them in ",[75,860,862],{"href":861},"\u002Farticles\u002Fpatching-jvms-inside-vendor-products","patching JVMs inside vendor products",[298,864,866],{"id":865},"application-servers","Application servers",[16,868,869],{},"Tomcat, WebLogic, WebSphere and JBoss\u002FWildFly installations usually point at a specific JDK through a startup script or environment file, not the system default. A server can have a patched JDK installed next to it while still running an old one.",[298,871,873],{"id":872},"containers","Containers",[16,875,876,877,880],{},"Every container image that includes Java carries its own runtime, fixed at build time. Patching the host changes nothing inside the container. When a base image is rebuilt rarely, or a team copied an old ",[331,878,879],{},"FROM"," line years ago, the vulnerable runtime ships to production on every deploy.",[298,882,884],{"id":883},"build-agents-and-desktop-tools","Build agents and desktop tools",[16,886,887],{},"CI runners, build agents, developer workstations and desktop tools such as IDEs, database clients and internal Swing apps all carry JVMs too. They're often left out of scope because \"they're not production.\" They still count toward license exposure, and build agents are an attractive target for attackers.",[11,889,891],{"id":890},"what-a-useful-inventory-captures","What a useful inventory captures",[16,893,894],{},"A list of hostnames with \"Java: yes\" doesn't help much. To drive decisions, each record needs:",[130,896,897,907],{},[133,898,899],{},[136,900,901,904],{},[139,902,903],{},"Field",[139,905,906],{},"Why it matters",[152,908,909,917,925,933,941,949,959],{},[136,910,911,914],{},[157,912,913],{},"Every running instance, across dev, staging and prod",[157,915,916],{},"Non-production environments still count for licensing and are still attack surface",[136,918,919,922],{},[157,920,921],{},"Version, vendor\u002Fdistribution and patch level",[157,923,924],{},"Oracle JDK vs. Temurin vs. Corretto vs. Zulu changes both licensing and the patch source",[136,926,927,930],{},[157,928,929],{},"Where it's embedded",[157,931,932],{},"Standalone app, app server, vendor product, or container image, since each is patched a different way",[136,934,935,938],{},[157,936,937],{},"CVE exposure, scored per JVM",[157,939,940],{},"A risk score per runtime, adjusted for exposure (such as internet-facing), not just a raw CVE count",[136,942,943,946],{},[157,944,945],{},"Owner",[157,947,948],{},"The person or team who can approve a change. Often the hardest field to fill in",[136,950,951,953],{},[157,952,60],{},[157,954,955,956],{},"APM, security and profiling Java agents are a leading cause of ",[75,957,958],{"href":462},"patch failures",[136,960,961,964],{},[157,962,963],{},"Criticality signal",[157,965,966],{},"Enough to seed a proper risk classification later",[16,968,969,970,974],{},"The last two fields are often skipped, and they're what turn an inventory into a patch plan. Knowing a JVM runs an APM agent tells you to test that agent before rollout. A criticality signal tells you which process the app should go through (see ",[75,971,973],{"href":972},"\u002Fapproach","our approach",").",[11,976,978],{"id":977},"how-to-collect-it","How to collect it",[16,980,981],{},"No single source is complete. The reliable approach combines several and reconciles them.",[298,983,985],{"id":984},"agentless-host-scanning","Agentless host scanning",[16,987,988],{},"Over SSH (Linux\u002FUnix) or WinRM (Windows), with a read-only account, you can:",[35,990,991,997,1000],{},[38,992,993,994,996],{},"List running processes and capture the full path of each ",[331,995,621],{}," executable",[38,998,999],{},"Search the filesystem for Java installations, including ones that aren't running",[38,1001,1002,1003,1006],{},"Read each installation's ",[331,1004,1005],{},"release"," file, which most modern JDKs and JREs include and which records the version and implementor",[16,1008,1009],{},"Here is a simple, read-only example for a Linux host:",[1011,1012,1016],"pre",{"className":1013,"code":1014,"language":1015,"meta":229,"style":229},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","# Running JVMs: resolve the actual binary behind each java process\nfor pid in $(pgrep -x java); do\n  bin=$(readlink -f \"\u002Fproc\u002F$pid\u002Fexe\" 2>\u002Fdev\u002Fnull)\n  echo \"running pid=$pid bin=$bin\"\ndone\n\n# Installed JVMs: find 'release' files next to a bin\u002Fjava, then print key fields\nfind \u002F -xdev -type f -name release -path '*\u002Frelease' 2>\u002Fdev\u002Fnull |\nwhile read -r f; do\n  dir=$(dirname \"$f\")\n  [ -x \"$dir\u002Fbin\u002Fjava\" ] || continue\n  echo \"== $dir\"\n  grep -E '^(JAVA_VERSION|IMPLEMENTOR|JAVA_RUNTIME_VERSION)=' \"$f\"\ndone\n","bash",[331,1017,1018,1026,1061,1104,1126,1131,1136,1142,1185,1204,1226,1253,1267,1289],{"__ignoreMap":229},[1019,1020,1022],"span",{"class":1021,"line":246},"line",[1019,1023,1025],{"class":1024},"sutJx","# Running JVMs: resolve the actual binary behind each java process\n",[1019,1027,1028,1032,1036,1039,1043,1047,1051,1055,1058],{"class":1021,"line":230},[1019,1029,1031],{"class":1030},"sVHd0","for",[1019,1033,1035],{"class":1034},"su5hD"," pid ",[1019,1037,1038],{"class":1030},"in",[1019,1040,1042],{"class":1041},"sP7_E"," $(",[1019,1044,1046],{"class":1045},"sbgvK","pgrep",[1019,1048,1050],{"class":1049},"stzsN"," -x",[1019,1052,1054],{"class":1053},"s_sjI"," java",[1019,1056,1057],{"class":1041},");",[1019,1059,1060],{"class":1030}," do\n",[1019,1062,1063,1066,1070,1073,1076,1079,1083,1086,1089,1092,1095,1098,1101],{"class":1021,"line":231},[1019,1064,1065],{"class":1034},"  bin",[1019,1067,1069],{"class":1068},"smGrS","=",[1019,1071,1072],{"class":1041},"$(",[1019,1074,1075],{"class":1045},"readlink",[1019,1077,1078],{"class":1049}," -f",[1019,1080,1082],{"class":1081},"sjJ54"," \"",[1019,1084,1085],{"class":1053},"\u002Fproc\u002F",[1019,1087,1088],{"class":1034},"$pid",[1019,1090,1091],{"class":1053},"\u002Fexe",[1019,1093,1094],{"class":1081},"\"",[1019,1096,1097],{"class":1068}," 2>",[1019,1099,1100],{"class":1053},"\u002Fdev\u002Fnull",[1019,1102,1103],{"class":1041},")\n",[1019,1105,1106,1110,1112,1115,1117,1120,1123],{"class":1021,"line":594},[1019,1107,1109],{"class":1108},"sptTA","  echo",[1019,1111,1082],{"class":1081},[1019,1113,1114],{"class":1053},"running pid=",[1019,1116,1088],{"class":1034},[1019,1118,1119],{"class":1053}," bin=",[1019,1121,1122],{"class":1034},"$bin",[1019,1124,1125],{"class":1081},"\"\n",[1019,1127,1128],{"class":1021,"line":682},[1019,1129,1130],{"class":1030},"done\n",[1019,1132,1133],{"class":1021,"line":767},[1019,1134,1135],{"emptyLinePlaceholder":245},"\n",[1019,1137,1139],{"class":1021,"line":1138},7,[1019,1140,1141],{"class":1024},"# Installed JVMs: find 'release' files next to a bin\u002Fjava, then print key fields\n",[1019,1143,1145,1148,1151,1154,1157,1160,1163,1166,1169,1172,1175,1178,1180,1182],{"class":1021,"line":1144},8,[1019,1146,1147],{"class":1045},"find",[1019,1149,1150],{"class":1053}," \u002F",[1019,1152,1153],{"class":1049}," -xdev",[1019,1155,1156],{"class":1049}," -type",[1019,1158,1159],{"class":1053}," f",[1019,1161,1162],{"class":1049}," -name",[1019,1164,1165],{"class":1053}," release",[1019,1167,1168],{"class":1049}," -path",[1019,1170,1171],{"class":1081}," '",[1019,1173,1174],{"class":1053},"*\u002Frelease",[1019,1176,1177],{"class":1081},"'",[1019,1179,1097],{"class":1068},[1019,1181,1100],{"class":1053},[1019,1183,1184],{"class":1068}," |\n",[1019,1186,1188,1191,1194,1197,1199,1202],{"class":1021,"line":1187},9,[1019,1189,1190],{"class":1030},"while",[1019,1192,1193],{"class":1053}," read",[1019,1195,1196],{"class":1049}," -r",[1019,1198,1159],{"class":1053},[1019,1200,1201],{"class":1041},";",[1019,1203,1060],{"class":1030},[1019,1205,1207,1210,1212,1214,1217,1219,1222,1224],{"class":1021,"line":1206},10,[1019,1208,1209],{"class":1034},"  dir",[1019,1211,1069],{"class":1068},[1019,1213,1072],{"class":1041},[1019,1215,1216],{"class":1045},"dirname",[1019,1218,1082],{"class":1081},[1019,1220,1221],{"class":1034},"$f",[1019,1223,1094],{"class":1081},[1019,1225,1103],{"class":1041},[1019,1227,1229,1232,1234,1236,1239,1242,1244,1247,1250],{"class":1021,"line":1228},11,[1019,1230,1231],{"class":1041},"  [",[1019,1233,1050],{"class":1068},[1019,1235,1082],{"class":1081},[1019,1237,1238],{"class":1034},"$dir",[1019,1240,1241],{"class":1053},"\u002Fbin\u002Fjava",[1019,1243,1094],{"class":1081},[1019,1245,1246],{"class":1041}," ]",[1019,1248,1249],{"class":1068}," ||",[1019,1251,1252],{"class":1030}," continue\n",[1019,1254,1256,1258,1260,1263,1265],{"class":1021,"line":1255},12,[1019,1257,1109],{"class":1108},[1019,1259,1082],{"class":1081},[1019,1261,1262],{"class":1053},"== ",[1019,1264,1238],{"class":1034},[1019,1266,1125],{"class":1081},[1019,1268,1270,1273,1276,1278,1281,1283,1285,1287],{"class":1021,"line":1269},13,[1019,1271,1272],{"class":1045},"  grep",[1019,1274,1275],{"class":1049}," -E",[1019,1277,1171],{"class":1081},[1019,1279,1280],{"class":1053},"^(JAVA_VERSION|IMPLEMENTOR|JAVA_RUNTIME_VERSION)=",[1019,1282,1177],{"class":1081},[1019,1284,1082],{"class":1081},[1019,1286,1221],{"class":1034},[1019,1288,1125],{"class":1081},[1019,1290,1292],{"class":1021,"line":1291},14,[1019,1293,1130],{"class":1030},[16,1295,1296,1297,1299,1300,1303],{},"Older runtimes, Java 8 and earlier in particular, may not have a ",[331,1298,1005],{}," file or may record fewer fields. For those, running ",[331,1301,1302],{},"\"$dir\u002Fbin\u002Fjava\" -version"," is the fallback. It executes the binary, so decide deliberately whether your access policy allows that.",[84,1305,1306],{},[16,1307,1308],{},"The script above only lists and reads. A production discovery tool also has to handle multiple filesystems, container overlay mounts, Windows registry entries and installers that rename directories.",[298,1310,1312],{"id":1311},"cmdb-and-configuration-management-reconciliation","CMDB and configuration-management reconciliation",[16,1314,1315],{},"Compare what you found with what your CMDB and your Ansible, Puppet or Chef data say should be there. The differences are often as valuable as the inventory itself: runtimes nobody registered, records for servers decommissioned years ago, and hosts where configuration management thinks it installed JDK 17 but something else is actually running.",[298,1317,111],{"id":1318},"cloud-provider-apis",[16,1320,1321],{},"AWS, Azure and GCP APIs list instances, managed container services and serverless functions, along with tags that often point to an owner or cost center. Serverless runtimes managed by the provider are a different conversation, but you still need to know they exist.",[298,1323,1325],{"id":1324},"container-image-scanning","Container image scanning",[16,1327,1328],{},"Scan the images in your registries and the images actually running in your clusters. Registry scanning finds what could be deployed. Cluster scanning finds what is deployed, including images from registries nobody remembers configuring.",[298,1330,1332],{"id":1331},"artifact-repository-scanning","Artifact repository scanning",[16,1334,1335],{},"Nexus and Artifactory hold the build outputs that become deployments. Scanning them finds embedded runtimes, such as a bundled JRE inside a distribution archive, before they're running anywhere.",[298,1337,1339],{"id":1338},"reuse-what-your-scanners-already-know","Reuse what your scanners already know",[16,1341,1342],{},"If you run a general-purpose vulnerability scanner, it has already seen many of these hosts. Use its data as an input rather than competing with it. What it usually can't do is interpret the results for Java specifically: which runtime a finding belongs to, whether it's embedded in a vendor product, what the patch path is, and what the licensing implication is.",[11,1344,1346],{"id":1345},"what-the-output-looks-like","What the output looks like",[16,1348,1349,1350,1353],{},"To make that concrete, here's an ",[20,1351,1352],{},"illustrative example",", not a real client result. A mid-sized estate assessment might report:",[35,1355,1356,1362,1368,1374],{},[38,1357,1358,1361],{},[20,1359,1360],{},"340 JVMs"," discovered, of which 118 were missing from the CMDB",[38,1363,1364,1367],{},[20,1365,1366],{},"60"," past end of public support",[38,1369,1370,1373],{},[20,1371,1372],{},"12"," with critical CVEs open for more than 400 days, several on internet-facing hosts",[38,1375,1376,1379,1380,1383],{},[20,1377,1378],{},"38"," Oracle JDK installations, which under Oracle's employee-based subscription can bring the whole headcount into license scope (see ",[75,1381,1382],{"href":350},"the employee metric explained",")",[16,1385,1386],{},"Numbers like these do what a policy memo can't: they give security, platform and finance a shared, specific reason to act.",[11,1388,1390],{"id":1389},"where-discovery-goes-wrong","Where discovery goes wrong",[298,1392,1394],{"id":1393},"ephemeral-workloads","Ephemeral workloads",[16,1396,1397],{},"Autoscaling groups, short-lived containers and batch jobs make \"inventory\" a moving target. A point-in-time scan will miss some of them. Decide early whether you're counting instances, images or both. Scanning images and deployment definitions usually gives a more stable picture than chasing instances.",[298,1399,1401],{"id":1400},"ownership-needs-people","Ownership needs people",[16,1403,1404],{},"Scanning can tell you what's running. It rarely tells you who's accountable for it. Tags, CMDB records and cost centers get you part of the way. The rest takes interviews and follow-up, so budget time for it instead of assuming it can be automated.",[298,1406,1408],{"id":1407},"access-and-data-handling","Access and data handling",[16,1410,1411],{},"Getting even read-only access across a fragmented estate is a procurement and security exercise in its own right. Ask for the minimum privilege that works, document exactly what's collected, and agree up front on data retention and handling. This matters most in regulated environments.",[466,1413,1414],{},[16,1415,1416],{},"Discovery is read-only, so it usually doesn't need a change ticket. That makes it the fastest way to start improving a Java estate without first winning a governance argument.",[11,1418,1420],{"id":1419},"what-to-do-next","What to do next",[16,1422,1423,1424,1427,1428,1431],{},"If you don't trust your current count, start with a scoped discovery of one business unit and compare it to what your records say. Our ",[75,1425,1426],{"href":253},"JVM discovery and estate assessment"," does exactly that. Once you have the inventory, ",[75,1429,1430],{"href":195},"drift monitoring"," keeps it current as the estate changes.",[1433,1434,1435],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":229,"searchDepth":230,"depth":231,"links":1437},[1438,1444,1445,1453,1454,1459],{"id":840,"depth":230,"text":841,"children":1439},[1440,1441,1442,1443],{"id":847,"depth":231,"text":848},{"id":865,"depth":231,"text":866},{"id":872,"depth":231,"text":873},{"id":883,"depth":231,"text":884},{"id":890,"depth":230,"text":891},{"id":977,"depth":230,"text":978,"children":1446},[1447,1448,1449,1450,1451,1452],{"id":984,"depth":231,"text":985},{"id":1311,"depth":231,"text":1312},{"id":1318,"depth":231,"text":111},{"id":1324,"depth":231,"text":1325},{"id":1331,"depth":231,"text":1332},{"id":1338,"depth":231,"text":1339},{"id":1345,"depth":230,"text":1346},{"id":1389,"depth":230,"text":1390,"children":1455},[1456,1457,1458],{"id":1393,"depth":231,"text":1394},{"id":1400,"depth":231,"text":1401},{"id":1407,"depth":231,"text":1408},{"id":1419,"depth":230,"text":1420},"2026-09-01","Most enterprises can't say how many JVMs they run or where. Here's what a useful JVM inventory captures, how to collect it, and where it goes wrong.",false,null,{},"\u002Farticles\u002Ffinding-every-jvm-in-your-estate",{"title":828,"description":1461},"articles\u002Ffinding-every-jvm-in-your-estate",[1469,1470,1471,1472,1473],"jvm-inventory","discovery","cmdb","shadow-it","cve-exposure","XR3LFg25kfTliwZn4qzUCfls8TdEZYhj6IWeKfSQGVk",[1476,1463],{"title":605,"path":689,"stem":691,"description":677,"children":-1},1790355850053]