[{"data":1,"prerenderedAt":4223},["ShallowReactive",2],{"articles-all":3,"services":3506},[4,447,809,1300,1946,2266,2687,3117],{"id":5,"title":6,"author":7,"body":8,"category":428,"date":429,"description":430,"draft":431,"extension":432,"featured":433,"image":434,"meta":435,"navigation":433,"path":436,"readingTime":437,"seo":438,"stem":439,"tags":440,"updated":434,"__hash__":446},"articles\u002Farticles\u002Fjava-21-nftc-free-period-ended.md","Oracle JDK 21's free update window has closed. Here's what that means.","patchmageddon-team",{"type":9,"value":10,"toc":412},"minimark",[11,15,18,23,26,45,48,115,118,122,125,131,137,140,146,149,153,156,159,173,176,182,186,191,194,202,206,209,212,216,219,242,250,254,338,341,344,348,389,395,399],[12,13,14],"p",{},"In September 2026, Oracle JDK 21 reached the end of its free commercial update window. If your organization runs Oracle JDK 21 in production and expects to keep patching it, the terms under which you receive those patches have changed.",[12,16,17],{},"This isn't a new policy. Oracle announced the model when it introduced the No-Fee Terms and Conditions (NFTC) license with JDK 17 in 2021, and the same thing happened to JDK 17 in 2024. Many teams treat \"Oracle made Java free again\" as a settled fact, though. For anyone on JDK 21 that is no longer true in the way that matters for security.",[19,20,22],"h2",{"id":21},"how-the-nftc-license-actually-works","How the NFTC license actually works",[12,24,25],{},"Starting with JDK 17, Oracle released Oracle JDK under the NFTC license, which allows free use, including commercial production use. The free period for each long-term support (LTS) release is time-limited:",[27,28,29,38],"ul",{},[30,31,32,33,37],"li",{},"An LTS release gets NFTC updates until ",[34,35,36],"strong",{},"one year after the next LTS release ships",".",[30,39,40,41,44],{},"After that, further updates for that release are published under the ",[34,42,43],{},"Oracle Technology Network (OTN) License Agreement for Java SE",". OTN allows personal, development and some other uses, but production commercial use needs a paid Java SE subscription.",[12,46,47],{},"Applied to recent LTS releases:",[49,50,51,70],"table",{},[52,53,54],"thead",{},[55,56,57,61,64,67],"tr",{},[58,59,60],"th",{},"LTS release",[58,62,63],{},"GA",[58,65,66],{},"Free (NFTC) updates until",[58,68,69],{},"Updates after that",[71,72,73,88,101],"tbody",{},[55,74,75,79,82,85],{},[76,77,78],"td",{},"JDK 17",[76,80,81],{},"September 2021",[76,83,84],{},"September 2024",[76,86,87],{},"OTN (subscription for commercial production use)",[55,89,90,93,96,99],{},[76,91,92],{},"JDK 21",[76,94,95],{},"September 2023",[76,97,98],{},"September 2026",[76,100,87],{},[55,102,103,106,109,112],{},[76,104,105],{},"JDK 25",[76,107,108],{},"September 2025",[76,110,111],{},"Expected around September 2028, one year after the next LTS",[76,113,114],{},"OTN",[12,116,117],{},"The JDK 25 date depends on Oracle keeping its two-year LTS cadence and its current NFTC terms. Both are Oracle's decisions, so treat the date as an expectation, not a guarantee.",[19,119,121],{"id":120},"what-changed-precisely","What changed, precisely",[12,123,124],{},"This is where a lot of internal conversations go wrong, so it's worth being exact.",[12,126,127,130],{},[34,128,129],{},"Builds already released under NFTC stay under NFTC."," If a server runs an Oracle JDK 21 update that was released under NFTC, that binary didn't change licenses overnight on September 16.",[12,132,133,136],{},[34,134,135],{},"What changed is what happens next."," Oracle JDK 21 updates released after the cutoff, starting with the next quarterly Critical Patch Update, come under the OTN license. Applying one of those updates to a production system without a subscription is where the compliance exposure starts.",[12,138,139],{},"So the real question isn't \"is our Java 21 still free?\" It's this:",[141,142,143],"blockquote",{},[12,144,145],{},"Do we want to keep receiving security patches for Oracle JDK 21 in production?",[12,147,148],{},"If yes, you pay. If no, the runtime stops getting security fixes, and each quarter adds new published CVEs against it. There isn't a free way to keep patching Oracle JDK 21.",[19,150,152],{"id":151},"the-october-patch-is-the-trap","The October patch is the trap",[12,154,155],{},"Oracle and the OpenJDK community release Java security updates quarterly: January, April, July and October. The October 2026 Critical Patch Update is the first Oracle JDK 21 update outside the free window.",[12,157,158],{},"In most estates, nobody will make a conscious decision to accept OTN terms. It will happen through normal operations:",[27,160,161,164,167,170],{},[30,162,163],{},"A platform team applies the October CPU on schedule because that's their job.",[30,165,166],{},"A golden image or base container image picks up the latest Oracle JDK 21 in its next rebuild.",[30,168,169],{},"An installer, configuration-management role or package repository mirror pulls \"latest 21\" by default.",[30,171,172],{},"A vulnerability scanner flags the old build as outdated and someone raises a ticket to update it.",[12,174,175],{},"Each of these is good security hygiene, and each can move a system from free to licensable without anyone in procurement knowing. This is the same pattern many organizations saw with JDK 17 in late 2024.",[177,178,179],"warning",{},[12,180,181],{},"If your patch automation targets \"latest Oracle JDK 21\", check it before the October Critical Patch Update lands. Pin it, point it at an OpenJDK build, or make sure the subscription decision has been made first.",[19,183,185],{"id":184},"your-three-options","Your three options",[187,188,190],"h3",{"id":189},"_1-subscribe","1. Subscribe",[12,192,193],{},"You can buy the Oracle Java SE Universal Subscription and keep patching Oracle JDK 21. This is a legitimate choice, especially where an application vendor certifies only Oracle JDK, or where you want Oracle's support.",[12,195,196,197,37],{},"Know what you're buying: the subscription is priced per employee across the whole organization, not per install. A small Oracle JDK footprint can still produce a large bill. We explain how the metric works in ",[198,199,201],"a",{"href":200},"\u002Farticles\u002Foracle-java-employee-metric-explained","how Oracle's employee-based Java metric works",[187,203,205],{"id":204},"_2-move-to-oracle-jdk-25-under-nftc","2. Move to Oracle JDK 25 under NFTC",[12,207,208],{},"JDK 25 is the current LTS and, at the time of writing, its updates are free under NFTC until roughly September 2028. Upgrading buys time.",[12,210,211],{},"It also means doing a major version upgrade, 21 to 25, which is a real engineering project, not a patch. The same cliff returns in about two years, when you'll need to decide again between paying, migrating and upgrading. Some teams are comfortable running that treadmill. Many decide it's cheaper to step off it once.",[187,213,215],{"id":214},"_3-migrate-to-an-openjdk-distribution","3. Migrate to an OpenJDK distribution",[12,217,218],{},"Oracle JDK is built from the OpenJDK source code. Several vendors ship free, TCK-tested OpenJDK builds with long-term security updates for JDK 21, and most also sell commercial support:",[27,220,221,224,227,230,233,236,239],{},[30,222,223],{},"Eclipse Temurin (Eclipse Adoptium)",[30,225,226],{},"Amazon Corretto",[30,228,229],{},"Azul Zulu",[30,231,232],{},"Red Hat build of OpenJDK",[30,234,235],{},"Microsoft Build of OpenJDK",[30,237,238],{},"BellSoft Liberica",[30,240,241],{},"IBM Semeru Runtimes (built on the Eclipse OpenJ9 VM instead of HotSpot, so it's a bigger change than the others)",[12,243,244,245,249],{},"For most server workloads, moving from Oracle JDK 21 to another vendor's JDK 21 is a same-version swap. It's lower risk than a major version upgrade, but it isn't zero risk. Trust stores, installer layout, bundled tooling and some defaults differ between vendors. Our ",[198,246,248],{"href":247},"\u002Farticles\u002Foracle-jdk-to-openjdk-migration-checklist","Oracle JDK to OpenJDK migration checklist"," covers what to verify.",[19,251,253],{"id":252},"picking-between-them","Picking between them",[49,255,256,271],{},[52,257,258],{},[55,259,260,262,265,268],{},[58,261],{},[58,263,264],{},"Subscribe",[58,266,267],{},"Upgrade to Oracle JDK 25",[58,269,270],{},"Migrate to OpenJDK 21",[71,272,273,286,300,314,326],{},[55,274,275,278,281,284],{},[76,276,277],{},"Keeps patches flowing",[76,279,280],{},"Yes",[76,282,283],{},"Yes, until ~2028",[76,285,280],{},[55,287,288,291,294,297],{},[76,289,290],{},"Engineering effort",[76,292,293],{},"Low",[76,295,296],{},"High (major upgrade)",[76,298,299],{},"Moderate (vendor swap)",[55,301,302,305,308,311],{},[76,303,304],{},"Recurring license cost",[76,306,307],{},"Yes, per employee",[76,309,310],{},"None for now",[76,312,313],{},"None; optional support",[55,315,316,319,322,324],{},[76,317,318],{},"Repeats in two years",[76,320,321],{},"No",[76,323,280],{},[76,325,321],{},[55,327,328,331,333,336],{},[76,329,330],{},"Works for vendor apps certified only on Oracle",[76,332,280],{},[76,334,335],{},"Depends on vendor",[76,337,335],{},[12,339,340],{},"Most estates end up with a mix. A few applications stay on Oracle because a vendor requires it. Most move to OpenJDK. A handful of teams already planning a 25 upgrade just bring it forward.",[12,342,343],{},"You can't make that decision well without knowing where every Oracle JDK 21 install actually is, who owns it and what depends on it.",[19,345,347],{"id":346},"what-to-do-this-quarter","What to do this quarter",[349,350,351,361,367,373,383],"ol",{},[30,352,353,356,357,37],{},[34,354,355],{},"Find every Oracle JDK in the estate."," That includes the JDKs bundled inside vendor products, container images and build agents, not only the ones on your standard server builds. See ",[198,358,360],{"href":359},"\u002Farticles\u002Ffinding-every-jvm-in-your-estate","finding every JVM in your estate",[30,362,363,366],{},[34,364,365],{},"Freeze automatic updates to Oracle JDK 21"," until a decision is made, so the October CPU doesn't make the decision for you.",[30,368,369,372],{},[34,370,371],{},"Split the inventory into three groups:"," migrate to OpenJDK, upgrade to 25, or keep on Oracle with a subscription. Record the reason for each keep.",[30,374,375,378,379,37],{},[34,376,377],{},"Move the easy majority first."," Same-version swaps on non-critical apps with good rollback can move quickly. See ",[198,380,382],{"href":381},"\u002Farticles\u002Ffast-detection-and-rollback-instead-of-regression-testing","fast detection and rollback instead of regression testing",[30,384,385,388],{},[34,386,387],{},"Keep evidence."," Record what was removed, when and where. If Oracle raises a licensing review later, dated evidence is what you'll want.",[390,391,392],"note",{},[12,393,394],{},"This article describes Oracle's published licensing model as we understand it. It is not legal advice. Check your own contracts and Oracle's current license terms, and involve your licensing or legal team before relying on any conclusion.",[19,396,398],{"id":397},"what-to-do-next","What to do next",[12,400,401,402,406,407,411],{},"If you don't have a current, trustworthy list of your Oracle JDK installs, start there. Our ",[198,403,405],{"href":404},"\u002Fservices\u002Fjvm-discovery","JVM discovery and estate assessment"," finds them, including the ones hidden inside other products. Our ",[198,408,410],{"href":409},"\u002Fservices\u002Fopenjdk-migration","OpenJDK migration service"," moves them off Oracle on a fixed timeline.",{"title":413,"searchDepth":414,"depth":415,"links":416},"",2,3,[417,418,419,420,425,426,427],{"id":21,"depth":414,"text":22},{"id":120,"depth":414,"text":121},{"id":151,"depth":414,"text":152},{"id":184,"depth":414,"text":185,"children":421},[422,423,424],{"id":189,"depth":415,"text":190},{"id":204,"depth":415,"text":205},{"id":214,"depth":415,"text":215},{"id":252,"depth":414,"text":253},{"id":346,"depth":414,"text":347},{"id":397,"depth":414,"text":398},"oracle-licensing","2026-09-22","Oracle JDK 21 updates released after September 2026 are no longer free for production use. Your options: pay, stop patching, or migrate to OpenJDK.",false,"md",true,null,{},"\u002Farticles\u002Fjava-21-nftc-free-period-ended",6,{"title":6,"description":430},"articles\u002Fjava-21-nftc-free-period-ended",[441,442,443,444,445],"oracle-java","licensing","nftc","jdk-21","openjdk","fHHAvnXDhd_YKKkTYB5LNWhx8YgENz3um2D6bkxDjYE",{"id":448,"title":449,"author":7,"body":450,"category":428,"date":799,"description":800,"draft":431,"extension":432,"featured":431,"image":434,"meta":801,"navigation":433,"path":200,"readingTime":802,"seo":803,"stem":804,"tags":805,"updated":434,"__hash__":808},"articles\u002Farticles\u002Foracle-java-employee-metric-explained.md","How Oracle's employee-based Java metric works, and why a few installs can price your whole company",{"type":9,"value":451,"toc":789},[452,455,466,470,473,484,487,507,519,523,534,537,614,620,624,631,642,645,653,660,663,669,673,676,679,696,706,710,713,730,733,737,740,763,766,770,773,778,780],[12,453,454],{},"Most software licenses scale with usage: more servers, more cores or more users means a bigger bill. Oracle's current Java SE subscription doesn't work that way, and that surprises a lot of finance and procurement teams the first time they see a quote.",[12,456,457,458,461,462,465],{},"Since January 2023, Oracle has sold Java SE commercially as the ",[34,459,460],{},"Java SE Universal Subscription",", priced on an ",[34,463,464],{},"employee"," metric. The count is based on the size of your organization, not on how much Java you run.",[19,467,469],{"id":468},"what-counts-as-an-employee","What counts as an \"employee\"",[12,471,472],{},"Oracle's definition is broad. Paraphrasing the published terms, the employee count includes:",[27,474,475,481],{},[30,476,477,478],{},"all full-time, part-time and temporary employees of your organization, ",[34,479,480],{},"and",[30,482,483],{},"all full-time, part-time and temporary employees of your agents, contractors, outsourcers and consultants who support your internal business operations.",[12,485,486],{},"A few implications follow:",[27,488,489,495,501],{},[30,490,491,494],{},[34,492,493],{},"It isn't limited to people who use Java."," Payroll, warehouse staff, sales and executives all count, whether or not they ever touch a Java application.",[30,496,497,500],{},[34,498,499],{},"It isn't limited to where Java runs."," One business unit running Oracle JDK doesn't limit the count to that business unit.",[30,502,503,506],{},[34,504,505],{},"Contractors and outsourcers can increase the number."," An outsourced service desk or a large offshore development partner may add materially to the total.",[12,508,509,510,513,514,518],{},"The number of installations, servers or processors doesn't enter the calculation. This is the core point: ",[34,511,512],{},"deployment footprint has almost no bearing on the price."," It mostly determines ",[515,516,517],"em",{},"whether"," you need a subscription at all.",[19,520,522],{"id":521},"the-published-price-bands","The published price bands",[12,524,525,526,529,530,533],{},"Oracle publishes list prices per employee per month, with volume bands. At the time of writing, the published list runs from ",[34,527,528],{},"$15 per employee per month"," in the smallest band down to ",[34,531,532],{},"$5.25"," in the largest published band. Organizations above the top band negotiate directly.",[12,535,536],{},"The bands as commonly cited from Oracle's price list:",[49,538,539,549],{},[52,540,541],{},[55,542,543,546],{},[58,544,545],{},"Total employees",[58,547,548],{},"List price per employee per month",[71,550,551,559,567,575,583,591,599,606],{},[55,552,553,556],{},[76,554,555],{},"1 – 999",[76,557,558],{},"$15.00",[55,560,561,564],{},[76,562,563],{},"1,000 – 2,999",[76,565,566],{},"$12.00",[55,568,569,572],{},[76,570,571],{},"3,000 – 9,999",[76,573,574],{},"$10.50",[55,576,577,580],{},[76,578,579],{},"10,000 – 19,999",[76,581,582],{},"$8.25",[55,584,585,588],{},[76,586,587],{},"20,000 – 29,999",[76,589,590],{},"$6.75",[55,592,593,596],{},[76,594,595],{},"30,000 – 39,999",[76,597,598],{},"$5.70",[55,600,601,604],{},[76,602,603],{},"40,000 – 49,999",[76,605,532],{},[55,607,608,611],{},[76,609,610],{},"50,000+",[76,612,613],{},"Negotiated",[615,616,617],"caution",{},[12,618,619],{},"List prices change and discounts vary. Always check Oracle's current Java SE price list and your own contract terms. Treat the figures here as a way to estimate the order of magnitude, not a quote.",[19,621,623],{"id":622},"a-worked-example","A worked example",[12,625,626,627,630],{},"Here's an ",[34,628,629],{},"illustrative"," organization, not a real client:",[27,632,633,636,639],{},[30,634,635],{},"5,000 employees, including in-scope contractors",[30,637,638],{},"Oracle JDK installed on 40 servers, running a handful of internal applications",[30,640,641],{},"No other Oracle Java use",[12,643,644],{},"At the 3,000–9,999 band list price of $10.50 per employee per month:",[141,646,647],{},[12,648,649,650],{},"5,000 employees × $10.50 × 12 months = ",[34,651,652],{},"$630,000 per year",[12,654,655,656,659],{},"That's roughly ",[34,657,658],{},"$15,750 per server per year"," for 40 servers, for a runtime that has free, drop-in-compatible alternatives.",[12,661,662],{},"Now suppose those 40 servers turn out to be 38 that can move to a free OpenJDK build and 2 running a vendor product certified only on Oracle JDK. The subscription price doesn't drop by 95%. It stays the same, because the metric is headcount. Removing Oracle JDK from 38 servers doesn't reduce the bill. Removing it from all 40 eliminates the bill.",[12,664,665,666,37],{},"This is why the employee metric makes licensing an ",[34,667,668],{},"all-or-nothing inventory problem",[19,670,672],{"id":671},"why-inventory-accuracy-is-the-lever","Why inventory accuracy is the lever",[12,674,675],{},"Under per-processor licensing, a slightly incomplete inventory meant a slightly wrong number. Under the employee metric, one forgotten install can carry the full cost.",[12,677,678],{},"The Oracle JDKs that cause problems are rarely on the standard server build. They tend to be:",[27,680,681,684,687,690,693],{},[30,682,683],{},"Old Oracle JDK 8 installs on long-lived servers that nobody has rebuilt",[30,685,686],{},"Oracle JDKs bundled into, or manually added to, vendor products and appliances",[30,688,689],{},"Developer tooling and build agents that fetched \"the Oracle JDK\" years ago",[30,691,692],{},"Base container images that were never updated",[30,694,695],{},"Desktop installs for a single legacy client application",[12,697,698,699,701,702,37],{},"Finding them takes more than querying the package manager on your standard Linux build. We describe what a complete discovery looks like in ",[198,700,360],{"href":359},", and the harder case of ",[198,703,705],{"href":704},"\u002Farticles\u002Fpatching-jvms-inside-vendor-products","JVMs bundled inside vendor products",[19,707,709],{"id":708},"not-every-oracle-jdk-is-automatically-in-scope","Not every Oracle JDK is automatically in scope",[12,711,712],{},"Two nuances are worth checking before assuming exposure:",[27,714,715,724],{},[30,716,717,720,721,37],{},[34,718,719],{},"Builds released under the No-Fee Terms and Conditions (NFTC) license."," Oracle JDK 17 and later have been released under NFTC for a limited period per release. A binary released under NFTC isn't necessarily a licensing problem on its own; updates released after the free window are. See ",[198,722,723],{"href":436},"what the end of the JDK 21 free window means",[30,725,726,729],{},[34,727,728],{},"Java included with another licensed product."," Some Oracle and third-party products include a restricted Java SE license for use with that product only. That usually doesn't cover general-purpose use of the same JDK by other applications on the same host.",[12,731,732],{},"Both depend on specific versions, dates and contract wording. That's exactly why the inventory needs to record version, vendor, build and what each JVM is used for, not just \"Java is installed here.\"",[19,734,736],{"id":735},"making-a-deliberate-decision","Making a deliberate decision",[12,738,739],{},"Once you know where every Oracle JDK is, the decision gets much clearer. For each install, choose one:",[349,741,742,751,757],{},[30,743,744,747,748,37],{},[34,745,746],{},"Migrate"," to a free OpenJDK build such as Eclipse Temurin, Amazon Corretto, Azul Zulu, Red Hat build of OpenJDK or Microsoft Build of OpenJDK. See our ",[198,749,750],{"href":247},"migration checklist",[30,752,753,756],{},[34,754,755],{},"Remove"," it if nothing actually uses it. This is more common than you'd expect.",[30,758,759,762],{},[34,760,761],{},"Keep"," it, deliberately, because a vendor requires it or Oracle support is worth the cost to you. If the answer for even one install is \"keep,\" price the subscription on your full employee count and decide knowingly.",[12,764,765],{},"What you want to avoid is the default outcome, where the subscription cost is set by an install nobody remembered.",[19,767,769],{"id":768},"a-note-on-audits-and-renewals","A note on audits and renewals",[12,771,772],{},"Oracle doesn't publish audit statistics. Licensing advisors report a steady volume of Java-related compliance conversations since the metric change. Whether a conversation starts from an audit, a renewal or an inbound sales call, the party with the accurate inventory negotiates from a much stronger position.",[390,774,775],{},[12,776,777],{},"This article explains Oracle's published Java SE licensing model as we understand it. It is not legal advice. Check your contracts, Oracle's current terms and price list, and involve your licensing and legal teams before making commitments.",[19,779,398],{"id":397},[12,781,782,783,785,786,788],{},"Start with the facts. Our ",[198,784,405],{"href":404}," quantifies your Oracle Java exposure against the employee metric, and our ",[198,787,410],{"href":409}," removes the installs that don't need to be there.",{"title":413,"searchDepth":414,"depth":415,"links":790},[791,792,793,794,795,796,797,798],{"id":468,"depth":414,"text":469},{"id":521,"depth":414,"text":522},{"id":622,"depth":414,"text":623},{"id":671,"depth":414,"text":672},{"id":708,"depth":414,"text":709},{"id":735,"depth":414,"text":736},{"id":768,"depth":414,"text":769},{"id":397,"depth":414,"text":398},"2026-09-15","Oracle's Java SE Universal Subscription is priced per employee, not per install. How the metric works, a worked example, and why your inventory drives the cost.",{},5,{"title":449,"description":800},"articles\u002Foracle-java-employee-metric-explained",[441,442,806,807],"java-se-subscription","cost","1jkg2uxHIWgnHabam8v1YiZLTRXXmSpnRSmbEqmkF3Y",{"id":810,"title":811,"author":7,"body":812,"category":1288,"date":1289,"description":1290,"draft":431,"extension":432,"featured":431,"image":434,"meta":1291,"navigation":433,"path":247,"readingTime":437,"seo":1292,"stem":1293,"tags":1294,"updated":434,"__hash__":1299},"articles\u002Farticles\u002Foracle-jdk-to-openjdk-migration-checklist.md","Oracle JDK to OpenJDK: a practical migration checklist",{"type":9,"value":813,"toc":1271},[814,821,824,827,831,834,851,856,860,863,952,955,993,997,1000,1004,1018,1022,1043,1047,1067,1071,1105,1109,1114,1118,1129,1133,1136,1156,1166,1170,1176,1202,1206,1212,1216,1260,1262],[12,815,816,817,820],{},"For most server workloads, moving from Oracle JDK to an OpenJDK distribution of the ",[34,818,819],{},"same version"," is one of the lowest-risk changes you can make to a Java runtime. Oracle JDK and the major OpenJDK builds come from the same source code, and the reputable distributions are tested against the Java SE Technology Compatibility Kit (TCK).",[12,822,823],{},"\"Low risk\" isn't \"no risk,\" though. The failures we see in vendor swaps are rarely about Java language behavior. They come from what surrounds the runtime: trust stores, install paths, startup flags, bundled components and applications that look for Oracle specifically.",[12,825,826],{},"This checklist is what we work through on every migration.",[19,828,830],{"id":829},"step-0-know-what-youre-migrating","Step 0: Know what you're migrating",[12,832,833],{},"You can't migrate what you haven't found. Before you pick a distribution, you need a list of every Oracle JDK and JRE with:",[27,835,836,839,842,845,848],{},[30,837,838],{},"host, container image or artifact where it lives",[30,840,841],{},"version and exact build",[30,843,844],{},"whether it's standalone, used by an app server, or bundled inside a vendor product",[30,846,847],{},"the application and owner that depend on it",[30,849,850],{},"how it gets there (golden image, config management, manual install, vendor installer)",[12,852,853,854,37],{},"That last field matters more than people expect. If you migrate a server but the golden image still installs Oracle JDK, it comes back on the next rebuild. See ",[198,855,360],{"href":359},[19,857,859],{"id":858},"step-1-choose-a-distribution","Step 1: Choose a distribution",[12,861,862],{},"Several vendors publish free, production-ready OpenJDK builds. Most also offer paid support. The main ones:",[49,864,865,878],{},[52,866,867],{},[55,868,869,872,875],{},[58,870,871],{},"Distribution",[58,873,874],{},"Maintainer",[58,876,877],{},"Notes",[71,879,880,891,901,911,921,931,941],{},[55,881,882,885,888],{},[76,883,884],{},"Eclipse Temurin",[76,886,887],{},"Eclipse Adoptium",[76,889,890],{},"Widely used vendor-neutral default; commercial support available from third parties",[55,892,893,895,898],{},[76,894,226],{},[76,896,897],{},"Amazon",[76,899,900],{},"Free; used heavily inside AWS",[55,902,903,905,908],{},[76,904,229],{},[76,906,907],{},"Azul",[76,909,910],{},"Free builds; broad platform and older-version coverage; paid support available",[55,912,913,915,918],{},[76,914,232],{},[76,916,917],{},"Red Hat",[76,919,920],{},"Natural fit for RHEL estates; supported through Red Hat subscriptions",[55,922,923,925,928],{},[76,924,235],{},[76,926,927],{},"Microsoft",[76,929,930],{},"Covers recent LTS releases (11 onward); used across Azure",[55,932,933,935,938],{},[76,934,238],{},[76,936,937],{},"BellSoft",[76,939,940],{},"Offers \"full\" builds that include JavaFX",[55,942,943,946,949],{},[76,944,945],{},"IBM Semeru Runtimes",[76,947,948],{},"IBM",[76,950,951],{},"Uses the Eclipse OpenJ9 VM, not HotSpot, so a bigger behavioral change",[12,953,954],{},"The criteria that actually matter:",[27,956,957,963,969,975,981,987],{},[30,958,959,962],{},[34,960,961],{},"LTS support length."," How long will this vendor ship security updates for the versions you run? Check the vendor's published roadmap for each version you need, especially Java 8 and 11.",[30,964,965,968],{},[34,966,967],{},"Update cadence."," Updates should follow the quarterly Critical Patch Update schedule (January, April, July, October), released promptly after each one.",[30,970,971,974],{},[34,972,973],{},"Commercial support."," Do you need a contract and an SLA for production incidents? Some distributions sell support directly; for others it's available from third parties.",[30,976,977,980],{},[34,978,979],{},"Platform coverage."," Operating systems, CPU architectures (x86-64, ARM64), container base images, and installers for Windows if you have Windows servers or desktops.",[30,982,983,986],{},[34,984,985],{},"TCK certification."," Confirm the builds you'll use are TCK-tested for the versions you need.",[30,988,989,992],{},[34,990,991],{},"Standardization."," One distribution across the estate is usually easier to patch, scan and support than several. Pick one default and allow exceptions only with a reason.",[19,994,996],{"id":995},"step-2-check-the-known-differences","Step 2: Check the known differences",[12,998,999],{},"These are the areas where vendor swaps actually cause problems.",[187,1001,1003],{"id":1002},"removed-or-unbundled-components-mostly-java-8","Removed or unbundled components (mostly Java 8)",[27,1005,1006,1012],{},[30,1007,1008,1011],{},[34,1009,1010],{},"JavaFX."," Oracle JDK 8 bundled JavaFX. Most OpenJDK 8 builds don't. Applications with JavaFX user interfaces need a build that includes it (some vendors offer these) or a separate OpenJFX dependency.",[30,1013,1014,1017],{},[34,1015,1016],{},"Java Web Start and the browser plugin."," These were part of Oracle JDK 8 but were never in OpenJDK, and were removed from Oracle JDK in 11. Applications launched via JNLP need an alternative launcher such as OpenWebStart, or a different delivery method.",[187,1019,1021],{"id":1020},"startup-flags","Startup flags",[27,1023,1024,1037],{},[30,1025,1026,1032,1033,1036],{},[34,1027,1028,37],{},[1029,1030,1031],"code",{},"-XX:+UnlockCommercialFeatures"," Older Oracle JDK 8 builds needed this flag to enable Java Flight Recorder, which was a commercial feature at the time. Startup scripts that still pass it may fail with an unrecognized-option error on other runtimes, which means the JVM ",[34,1034,1035],{},"doesn't start",". Search every start script, service unit, container entrypoint and app-server config for commercial and Oracle-specific flags.",[30,1038,1039,1042],{},[34,1040,1041],{},"Deprecated or obsolete flags"," in general. If the migration also changes the build level, check the startup options against the target version's documentation.",[187,1044,1046],{"id":1045},"trust-stores","Trust stores",[27,1048,1049,1058],{},[30,1050,1051,1057],{},[34,1052,1053,1056],{},[1029,1054,1055],{},"cacerts"," contents differ between vendors."," Each distribution curates its own default set of trusted root CAs. If an application connects to a partner or internal service whose certificate chains to a root that's in Oracle's store but not your new vendor's, TLS handshakes will fail.",[30,1059,1060,1063,1064,1066],{},[34,1061,1062],{},"Custom certificates added by hand"," to the old JDK's ",[1029,1065,1055],{}," will not be carried over. Inventory them and re-import them, or better, move to a managed trust store outside the JDK directory.",[187,1068,1070],{"id":1069},"paths-installers-and-registry-keys","Paths, installers and registry keys",[27,1072,1073,1082,1091],{},[30,1074,1075,1081],{},[34,1076,1077,1080],{},[1029,1078,1079],{},"JAVA_HOME"," and hard-coded paths."," Scripts and service definitions often point at paths like an Oracle-specific install directory. Find them before you uninstall anything.",[30,1083,1084,1087,1088,1090],{},[34,1085,1086],{},"Windows registry keys."," Some applications find Java through Oracle's registry entries instead of ",[1029,1089,1079],{},". Check whether your chosen distribution's installer can set compatible keys, and test the applications that depend on them.",[30,1092,1093,1096,1097,1100,1101,1104],{},[34,1094,1095],{},"Alternatives and symlinks"," on Linux. Make sure ",[1029,1098,1099],{},"java"," on the ",[1029,1102,1103],{},"PATH"," resolves to the runtime you think it does.",[187,1106,1108],{"id":1107},"rendering-and-fonts","Rendering and fonts",[27,1110,1111],{},[30,1112,1113],{},"Older Oracle JDK 8 builds used a different font rasterizer from OpenJDK builds, so reports, PDF generation and desktop UIs can render text slightly differently. This rarely matters for services, but it can for document-generation workloads.",[187,1115,1117],{"id":1116},"vendor-certification","Vendor certification",[27,1119,1120],{},[30,1121,1122,1125,1126,37],{},[34,1123,1124],{},"Third-party products that certify only Oracle JDK."," Some commercial applications list only Oracle JDK in their support matrix. Running them on another build may be technically fine and still unsupported. Ask the vendor, get the answer in writing, and record it. See ",[198,1127,1128],{"href":704},"patching JVMs inside vendor products",[19,1130,1132],{"id":1131},"step-3-verify-then-roll-out-progressively","Step 3: Verify, then roll out progressively",[12,1134,1135],{},"For a same-version vendor swap on a non-critical application, you usually don't need a full regression cycle. You do need:",[349,1137,1138,1144,1150],{},[30,1139,1140,1143],{},[34,1141,1142],{},"Smoke tests"," covering startup, the main user paths, outbound TLS connections and scheduled jobs.",[30,1145,1146,1149],{},[34,1147,1148],{},"A canary."," Move one instance or a small share of traffic first, and compare error rates, latency, GC behavior and log noise with the old runtime.",[30,1151,1152,1155],{},[34,1153,1154],{},"A tested rollback."," Keep the previous runtime available until the new one has been stable for an agreed period, and know exactly how to switch back.",[12,1157,1158,1159,1161,1162,37],{},"For business-critical systems, add shadow-traffic comparison or targeted regression tests on the paths most exposed to runtime differences. We describe the thinking in ",[198,1160,382],{"href":381}," and the common failure patterns in ",[198,1163,1165],{"href":1164},"\u002Farticles\u002Fjvm-patch-failure-modes","how JVM patches break production",[19,1167,1169],{"id":1168},"step-4-remove-oracle-dont-just-re-point","Step 4: Remove Oracle, don't just re-point",[12,1171,1172,1173,1175],{},"This is where many migrations stop short. Changing ",[1029,1174,1079],{}," to the new runtime leaves the Oracle binaries on disk, and from a licensing point of view an installed Oracle JDK is still an Oracle JDK.",[27,1177,1178,1184,1190,1196],{},[30,1179,1180,1183],{},[34,1181,1182],{},"Uninstall"," Oracle JDK and JRE packages, and delete leftover directories.",[30,1185,1186,1189],{},[34,1187,1188],{},"Update the sources",": golden images, container base images, configuration-management roles, internal package mirrors and software catalogs.",[30,1191,1192,1195],{},[34,1193,1194],{},"Block reintroduction."," Add a check in image builds or CI that fails if an Oracle JDK appears.",[30,1197,1198,1201],{},[34,1199,1200],{},"Re-scan"," after cleanup to confirm nothing remains.",[19,1203,1205],{"id":1204},"step-5-keep-the-evidence","Step 5: Keep the evidence",[12,1207,1208,1209,37],{},"Record what was migrated or removed, where, when and by whom, with before-and-after scan output. If a licensing review happens later, dated evidence of removal is far more persuasive than a statement that \"we moved off Oracle last year.\" This matters especially given ",[198,1210,1211],{"href":200},"how Oracle's employee-based metric works",[19,1213,1215],{"id":1214},"the-checklist","The checklist",[349,1217,1218,1221,1224,1227,1230,1236,1239,1245,1248,1251,1254,1257],{},[30,1219,1220],{},"Build a complete inventory of Oracle JDK and JRE installs, including bundled and containerized ones.",[30,1222,1223],{},"Record the owner, the dependent applications and how each install gets provisioned.",[30,1225,1226],{},"Choose a default OpenJDK distribution and document the exceptions policy.",[30,1228,1229],{},"Flag JavaFX, Java Web Start and other Oracle-8-only dependencies.",[30,1231,1232,1233,1235],{},"Search startup configuration for ",[1029,1234,1031],{}," and other Oracle-specific or obsolete flags.",[30,1237,1238],{},"Compare trust stores and re-import custom certificates.",[30,1240,1241,1242,1244],{},"Find hard-coded paths, ",[1029,1243,1079],{}," settings and registry dependencies.",[30,1246,1247],{},"Confirm vendor support for third-party products, in writing.",[30,1249,1250],{},"Smoke test, canary and keep a rehearsed rollback.",[30,1252,1253],{},"Uninstall Oracle binaries and fix the golden images and automation that installed them.",[30,1255,1256],{},"Re-scan to confirm removal.",[30,1258,1259],{},"Archive the evidence.",[19,1261,398],{"id":397},[12,1263,1264,1265,1267,1268,1270],{},"If you want this done on a fixed timeline, our ",[198,1266,410],{"href":409}," runs the whole checklist, starting from a ",[198,1269,405],{"href":404}," so nothing gets missed.",{"title":413,"searchDepth":414,"depth":415,"links":1272},[1273,1274,1275,1283,1284,1285,1286,1287],{"id":829,"depth":414,"text":830},{"id":858,"depth":414,"text":859},{"id":995,"depth":414,"text":996,"children":1276},[1277,1278,1279,1280,1281,1282],{"id":1002,"depth":415,"text":1003},{"id":1020,"depth":415,"text":1021},{"id":1045,"depth":415,"text":1046},{"id":1069,"depth":415,"text":1070},{"id":1107,"depth":415,"text":1108},{"id":1116,"depth":415,"text":1117},{"id":1131,"depth":414,"text":1132},{"id":1168,"depth":414,"text":1169},{"id":1204,"depth":414,"text":1205},{"id":1214,"depth":414,"text":1215},{"id":397,"depth":414,"text":398},"openjdk-migration","2026-09-08","A step-by-step checklist for moving from Oracle JDK to an OpenJDK build: choosing a distribution, what differs between vendors, verification and cleanup.",{},{"title":811,"description":1290},"articles\u002Foracle-jdk-to-openjdk-migration-checklist",[445,441,1295,1296,1297,1298],"migration","temurin","corretto","zulu","3wYnAM2s__rsMjzNJvmeHU4vhiOOa4RHGxad2U61D08",{"id":1301,"title":1302,"author":7,"body":1303,"category":1933,"date":1934,"description":1935,"draft":431,"extension":432,"featured":431,"image":434,"meta":1936,"navigation":433,"path":359,"readingTime":437,"seo":1937,"stem":1938,"tags":1939,"updated":434,"__hash__":1945},"articles\u002Farticles\u002Ffinding-every-jvm-in-your-estate.md","You can't patch what you can't find: building a real JVM inventory",{"type":9,"value":1304,"toc":1909},[1305,1308,1311,1315,1318,1322,1328,1333,1337,1340,1344,1351,1355,1358,1362,1365,1438,1446,1450,1453,1457,1460,1478,1481,1767,1777,1782,1786,1789,1793,1796,1800,1803,1807,1810,1814,1817,1821,1828,1858,1861,1865,1869,1872,1876,1879,1883,1886,1892,1894,1905],[12,1306,1307],{},"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.",[12,1309,1310],{},"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.",[19,1312,1314],{"id":1313},"why-nobody-has-an-accurate-list","Why nobody has an accurate list",[12,1316,1317],{},"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.",[187,1319,1321],{"id":1320},"shadow-jvms-inside-vendor-products","Shadow JVMs inside vendor products",[12,1323,1324,1325,1327],{},"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 ",[1029,1326,1103],{},", it doesn't show up in the OS package manager, and the team that installed the product often doesn't know it's there.",[12,1329,1330,1331,37],{},"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 ",[198,1332,1128],{"href":704},[187,1334,1336],{"id":1335},"application-servers","Application servers",[12,1338,1339],{},"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.",[187,1341,1343],{"id":1342},"containers","Containers",[12,1345,1346,1347,1350],{},"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 ",[1029,1348,1349],{},"FROM"," line years ago, the vulnerable runtime ships to production on every deploy.",[187,1352,1354],{"id":1353},"build-agents-and-desktop-tools","Build agents and desktop tools",[12,1356,1357],{},"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.",[19,1359,1361],{"id":1360},"what-a-useful-inventory-captures","What a useful inventory captures",[12,1363,1364],{},"A list of hostnames with \"Java: yes\" doesn't help much. To drive decisions, each record needs:",[49,1366,1367,1377],{},[52,1368,1369],{},[55,1370,1371,1374],{},[58,1372,1373],{},"Field",[58,1375,1376],{},"Why it matters",[71,1378,1379,1387,1395,1403,1411,1419,1430],{},[55,1380,1381,1384],{},[76,1382,1383],{},"Every running instance, across dev, staging and prod",[76,1385,1386],{},"Non-production environments still count for licensing and are still attack surface",[55,1388,1389,1392],{},[76,1390,1391],{},"Version, vendor\u002Fdistribution and patch level",[76,1393,1394],{},"Oracle JDK vs. Temurin vs. Corretto vs. Zulu changes both licensing and the patch source",[55,1396,1397,1400],{},[76,1398,1399],{},"Where it's embedded",[76,1401,1402],{},"Standalone app, app server, vendor product, or container image, since each is patched a different way",[55,1404,1405,1408],{},[76,1406,1407],{},"CVE exposure, scored per JVM",[76,1409,1410],{},"A risk score per runtime, adjusted for exposure (such as internet-facing), not just a raw CVE count",[55,1412,1413,1416],{},[76,1414,1415],{},"Owner",[76,1417,1418],{},"The person or team who can approve a change. Often the hardest field to fill in",[55,1420,1421,1424],{},[76,1422,1423],{},"Installed agents",[76,1425,1426,1427],{},"APM, security and profiling Java agents are a leading cause of ",[198,1428,1429],{"href":1164},"patch failures",[55,1431,1432,1435],{},[76,1433,1434],{},"Criticality signal",[76,1436,1437],{},"Enough to seed a proper risk classification later",[12,1439,1440,1441,1445],{},"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 ",[198,1442,1444],{"href":1443},"\u002Fapproach","our approach",").",[19,1447,1449],{"id":1448},"how-to-collect-it","How to collect it",[12,1451,1452],{},"No single source is complete. The reliable approach combines several and reconciles them.",[187,1454,1456],{"id":1455},"agentless-host-scanning","Agentless host scanning",[12,1458,1459],{},"Over SSH (Linux\u002FUnix) or WinRM (Windows), with a read-only account, you can:",[27,1461,1462,1468,1471],{},[30,1463,1464,1465,1467],{},"List running processes and capture the full path of each ",[1029,1466,1099],{}," executable",[30,1469,1470],{},"Search the filesystem for Java installations, including ones that aren't running",[30,1472,1473,1474,1477],{},"Read each installation's ",[1029,1475,1476],{},"release"," file, which most modern JDKs and JREs include and which records the version and implementor",[12,1479,1480],{},"Here is a simple, read-only example for a Linux host:",[1482,1483,1487],"pre",{"className":1484,"code":1485,"language":1486,"meta":413,"style":413},"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",[1029,1488,1489,1498,1533,1576,1599,1604,1609,1615,1658,1677,1699,1726,1740,1762],{"__ignoreMap":413},[1490,1491,1494],"span",{"class":1492,"line":1493},"line",1,[1490,1495,1497],{"class":1496},"sutJx","# Running JVMs: resolve the actual binary behind each java process\n",[1490,1499,1500,1504,1508,1511,1515,1519,1523,1527,1530],{"class":1492,"line":414},[1490,1501,1503],{"class":1502},"sVHd0","for",[1490,1505,1507],{"class":1506},"su5hD"," pid ",[1490,1509,1510],{"class":1502},"in",[1490,1512,1514],{"class":1513},"sP7_E"," $(",[1490,1516,1518],{"class":1517},"sbgvK","pgrep",[1490,1520,1522],{"class":1521},"stzsN"," -x",[1490,1524,1526],{"class":1525},"s_sjI"," java",[1490,1528,1529],{"class":1513},");",[1490,1531,1532],{"class":1502}," do\n",[1490,1534,1535,1538,1542,1545,1548,1551,1555,1558,1561,1564,1567,1570,1573],{"class":1492,"line":415},[1490,1536,1537],{"class":1506},"  bin",[1490,1539,1541],{"class":1540},"smGrS","=",[1490,1543,1544],{"class":1513},"$(",[1490,1546,1547],{"class":1517},"readlink",[1490,1549,1550],{"class":1521}," -f",[1490,1552,1554],{"class":1553},"sjJ54"," \"",[1490,1556,1557],{"class":1525},"\u002Fproc\u002F",[1490,1559,1560],{"class":1506},"$pid",[1490,1562,1563],{"class":1525},"\u002Fexe",[1490,1565,1566],{"class":1553},"\"",[1490,1568,1569],{"class":1540}," 2>",[1490,1571,1572],{"class":1525},"\u002Fdev\u002Fnull",[1490,1574,1575],{"class":1513},")\n",[1490,1577,1579,1583,1585,1588,1590,1593,1596],{"class":1492,"line":1578},4,[1490,1580,1582],{"class":1581},"sptTA","  echo",[1490,1584,1554],{"class":1553},[1490,1586,1587],{"class":1525},"running pid=",[1490,1589,1560],{"class":1506},[1490,1591,1592],{"class":1525}," bin=",[1490,1594,1595],{"class":1506},"$bin",[1490,1597,1598],{"class":1553},"\"\n",[1490,1600,1601],{"class":1492,"line":802},[1490,1602,1603],{"class":1502},"done\n",[1490,1605,1606],{"class":1492,"line":437},[1490,1607,1608],{"emptyLinePlaceholder":433},"\n",[1490,1610,1612],{"class":1492,"line":1611},7,[1490,1613,1614],{"class":1496},"# Installed JVMs: find 'release' files next to a bin\u002Fjava, then print key fields\n",[1490,1616,1618,1621,1624,1627,1630,1633,1636,1639,1642,1645,1648,1651,1653,1655],{"class":1492,"line":1617},8,[1490,1619,1620],{"class":1517},"find",[1490,1622,1623],{"class":1525}," \u002F",[1490,1625,1626],{"class":1521}," -xdev",[1490,1628,1629],{"class":1521}," -type",[1490,1631,1632],{"class":1525}," f",[1490,1634,1635],{"class":1521}," -name",[1490,1637,1638],{"class":1525}," release",[1490,1640,1641],{"class":1521}," -path",[1490,1643,1644],{"class":1553}," '",[1490,1646,1647],{"class":1525},"*\u002Frelease",[1490,1649,1650],{"class":1553},"'",[1490,1652,1569],{"class":1540},[1490,1654,1572],{"class":1525},[1490,1656,1657],{"class":1540}," |\n",[1490,1659,1661,1664,1667,1670,1672,1675],{"class":1492,"line":1660},9,[1490,1662,1663],{"class":1502},"while",[1490,1665,1666],{"class":1525}," read",[1490,1668,1669],{"class":1521}," -r",[1490,1671,1632],{"class":1525},[1490,1673,1674],{"class":1513},";",[1490,1676,1532],{"class":1502},[1490,1678,1680,1683,1685,1687,1690,1692,1695,1697],{"class":1492,"line":1679},10,[1490,1681,1682],{"class":1506},"  dir",[1490,1684,1541],{"class":1540},[1490,1686,1544],{"class":1513},[1490,1688,1689],{"class":1517},"dirname",[1490,1691,1554],{"class":1553},[1490,1693,1694],{"class":1506},"$f",[1490,1696,1566],{"class":1553},[1490,1698,1575],{"class":1513},[1490,1700,1702,1705,1707,1709,1712,1715,1717,1720,1723],{"class":1492,"line":1701},11,[1490,1703,1704],{"class":1513},"  [",[1490,1706,1522],{"class":1540},[1490,1708,1554],{"class":1553},[1490,1710,1711],{"class":1506},"$dir",[1490,1713,1714],{"class":1525},"\u002Fbin\u002Fjava",[1490,1716,1566],{"class":1553},[1490,1718,1719],{"class":1513}," ]",[1490,1721,1722],{"class":1540}," ||",[1490,1724,1725],{"class":1502}," continue\n",[1490,1727,1729,1731,1733,1736,1738],{"class":1492,"line":1728},12,[1490,1730,1582],{"class":1581},[1490,1732,1554],{"class":1553},[1490,1734,1735],{"class":1525},"== ",[1490,1737,1711],{"class":1506},[1490,1739,1598],{"class":1553},[1490,1741,1743,1746,1749,1751,1754,1756,1758,1760],{"class":1492,"line":1742},13,[1490,1744,1745],{"class":1517},"  grep",[1490,1747,1748],{"class":1521}," -E",[1490,1750,1644],{"class":1553},[1490,1752,1753],{"class":1525},"^(JAVA_VERSION|IMPLEMENTOR|JAVA_RUNTIME_VERSION)=",[1490,1755,1650],{"class":1553},[1490,1757,1554],{"class":1553},[1490,1759,1694],{"class":1506},[1490,1761,1598],{"class":1553},[1490,1763,1765],{"class":1492,"line":1764},14,[1490,1766,1603],{"class":1502},[12,1768,1769,1770,1772,1773,1776],{},"Older runtimes, Java 8 and earlier in particular, may not have a ",[1029,1771,1476],{}," file or may record fewer fields. For those, running ",[1029,1774,1775],{},"\"$dir\u002Fbin\u002Fjava\" -version"," is the fallback. It executes the binary, so decide deliberately whether your access policy allows that.",[390,1778,1779],{},[12,1780,1781],{},"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.",[187,1783,1785],{"id":1784},"cmdb-and-configuration-management-reconciliation","CMDB and configuration-management reconciliation",[12,1787,1788],{},"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.",[187,1790,1792],{"id":1791},"cloud-provider-apis","Cloud provider APIs",[12,1794,1795],{},"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.",[187,1797,1799],{"id":1798},"container-image-scanning","Container image scanning",[12,1801,1802],{},"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.",[187,1804,1806],{"id":1805},"artifact-repository-scanning","Artifact repository scanning",[12,1808,1809],{},"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.",[187,1811,1813],{"id":1812},"reuse-what-your-scanners-already-know","Reuse what your scanners already know",[12,1815,1816],{},"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.",[19,1818,1820],{"id":1819},"what-the-output-looks-like","What the output looks like",[12,1822,1823,1824,1827],{},"To make that concrete, here's an ",[34,1825,1826],{},"illustrative example",", not a real client result. A mid-sized estate assessment might report:",[27,1829,1830,1836,1842,1848],{},[30,1831,1832,1835],{},[34,1833,1834],{},"340 JVMs"," discovered, of which 118 were missing from the CMDB",[30,1837,1838,1841],{},[34,1839,1840],{},"60"," past end of public support",[30,1843,1844,1847],{},[34,1845,1846],{},"12"," with critical CVEs open for more than 400 days, several on internet-facing hosts",[30,1849,1850,1853,1854,1857],{},[34,1851,1852],{},"38"," Oracle JDK installations, which under Oracle's employee-based subscription can bring the whole headcount into license scope (see ",[198,1855,1856],{"href":200},"the employee metric explained",")",[12,1859,1860],{},"Numbers like these do what a policy memo can't: they give security, platform and finance a shared, specific reason to act.",[19,1862,1864],{"id":1863},"where-discovery-goes-wrong","Where discovery goes wrong",[187,1866,1868],{"id":1867},"ephemeral-workloads","Ephemeral workloads",[12,1870,1871],{},"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.",[187,1873,1875],{"id":1874},"ownership-needs-people","Ownership needs people",[12,1877,1878],{},"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.",[187,1880,1882],{"id":1881},"access-and-data-handling","Access and data handling",[12,1884,1885],{},"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.",[1887,1888,1889],"tip",{},[12,1890,1891],{},"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.",[19,1893,398],{"id":397},[12,1895,1896,1897,1899,1900,1904],{},"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 ",[198,1898,405],{"href":404}," does exactly that. Once you have the inventory, ",[198,1901,1903],{"href":1902},"\u002Fservices\u002Fdrift-monitoring","drift monitoring"," keeps it current as the estate changes.",[1906,1907,1908],"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":413,"searchDepth":414,"depth":415,"links":1910},[1911,1917,1918,1926,1927,1932],{"id":1313,"depth":414,"text":1314,"children":1912},[1913,1914,1915,1916],{"id":1320,"depth":415,"text":1321},{"id":1335,"depth":415,"text":1336},{"id":1342,"depth":415,"text":1343},{"id":1353,"depth":415,"text":1354},{"id":1360,"depth":414,"text":1361},{"id":1448,"depth":414,"text":1449,"children":1919},[1920,1921,1922,1923,1924,1925],{"id":1455,"depth":415,"text":1456},{"id":1784,"depth":415,"text":1785},{"id":1791,"depth":415,"text":1792},{"id":1798,"depth":415,"text":1799},{"id":1805,"depth":415,"text":1806},{"id":1812,"depth":415,"text":1813},{"id":1819,"depth":414,"text":1820},{"id":1863,"depth":414,"text":1864,"children":1928},[1929,1930,1931],{"id":1867,"depth":415,"text":1868},{"id":1874,"depth":415,"text":1875},{"id":1881,"depth":415,"text":1882},{"id":397,"depth":414,"text":398},"jvm-discovery","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.",{},{"title":1302,"description":1935},"articles\u002Ffinding-every-jvm-in-your-estate",[1940,1941,1942,1943,1944],"jvm-inventory","discovery","cmdb","shadow-it","cve-exposure","XR3LFg25kfTliwZn4qzUCfls8TdEZYhj6IWeKfSQGVk",{"id":1947,"title":1948,"author":7,"body":1949,"category":2252,"date":2253,"description":2254,"draft":431,"extension":432,"featured":431,"image":434,"meta":2255,"navigation":433,"path":2256,"readingTime":802,"seo":2257,"stem":2258,"tags":2259,"updated":434,"__hash__":2265},"articles\u002Farticles\u002Fcab-approval-for-faster-jvm-patching.md","How to get your CAB to approve faster JVM patching",{"type":9,"value":1950,"toc":2241},[1951,1954,1957,1961,1964,1969,1972,1976,1979,1982,1985,2017,2020,2025,2029,2032,2039,2043,2050,2104,2111,2115,2118,2156,2159,2163,2166,2169,2186,2191,2195,2198,2202,2205,2216,2219,2224,2226],[12,1952,1953],{},"Most proposals to speed up JVM patching fail in the same place, and it isn't technical. The engineering team shows that a same-major security update is low risk, that rollout can be progressive, and that rollback is quick. Then the proposal goes to the Change Advisory Board and stalls.",[12,1955,1956],{},"The CAB isn't being obstructive. Its job is to make sure changes are understood, owned and reversible, and \"we'd like to test less\" doesn't sound like any of those. The way through is to give the CAB a better process to approve, not to argue that the current one is too slow.",[19,1958,1960],{"id":1959},"reframe-the-ask","Reframe the ask",[12,1962,1963],{},"\"Skip regression testing for these apps\" is a hard sell to a risk function. It describes removing a control.",[12,1965,1966,1967,37],{},"\"For a defined tier of applications, replace pre-deployment regression testing with fast detection and fast rollback\" is a different proposal. It swaps one control for another and can be measured. You can show how quickly a bad patch would be detected, how quickly it would be reversed, and what evidence gets recorded along the way. The engineering case is set out in ",[198,1968,382],{"href":381},[12,1970,1971],{},"The rest of this article covers what makes that proposal approvable.",[19,1973,1975],{"id":1974},"criticality-has-to-be-scored-not-self-declared","Criticality has to be scored, not self-declared",[12,1977,1978],{},"The first thing a CAB will ask is: which applications are in the fast tier, and who decided?",[12,1980,1981],{},"If the answer is \"the app owners told us,\" the proposal won't survive. App owners have every reason to call their app non-critical, since it means fewer approvals and less paperwork, and they're rarely the ones who bear the consequences of being wrong.",[12,1983,1984],{},"Classification needs to be a documented, repeatable scoring process. The dimensions we use include:",[27,1986,1987,1993,1999,2005,2011],{},[30,1988,1989,1992],{},[34,1990,1991],{},"Revenue and customer impact:"," what breaks, for whom, and the cost per hour of downtime",[30,1994,1995,1998],{},[34,1996,1997],{},"Blast radius:"," shared infrastructure, shared databases or a shared message bus with critical systems",[30,2000,2001,2004],{},[34,2002,2003],{},"Regulatory scope:"," whether the app handles data covered by PCI DSS, HIPAA, SOX or similar. Many \"internal tools\" do",[30,2006,2007,2010],{},[34,2008,2009],{},"SLA and SLO commitments:"," whether one exists and at what tier",[30,2012,2013,2016],{},[34,2014,2015],{},"Risk-acceptor authority:"," who can accept the risk, and whether they actually have the authority to do so",[12,2018,2019],{},"Some of these can be derived from discovery data (exposure, dependencies, existing SLA metadata). Others need a short, standardized owner interview. Using the same fixed questions for every app is what makes fifty classifications consistent with each other.",[390,2021,2022],{},[12,2023,2024],{},"How you weight the dimensions is a decision for your organization. What matters to the CAB is that the weights are documented, applied the same way every time, and reviewable.",[19,2026,2028],{"id":2027},"set-thresholds-before-you-score-anything","Set thresholds before you score anything",[12,2030,2031],{},"Score bands should route each app to a tier: fast-track patching, a higher-assurance process for business-critical apps, or manual review for scores near a boundary.",[12,2033,2034,2035,2038],{},"Define those thresholds ",[34,2036,2037],{},"before"," scoring the first application. Thresholds set after you've seen the scores look like rationalization, even when they aren't. Thresholds agreed in advance and written down are what make the routing defensible to an auditor.",[19,2040,2042],{"id":2041},"use-the-standard-change-model","Use the standard change model",[12,2044,2045,2046,2049],{},"ITIL already has a concept that fits: the ",[34,2047,2048],{},"standard change",", a low-risk, well-understood change that is pre-authorized and follows a documented procedure. You don't need the CAB to approve each quarterly JVM patch on each app. You need it to approve a standard change model once:",[49,2051,2052,2062],{},[52,2053,2054],{},[55,2055,2056,2059],{},[58,2057,2058],{},"Element",[58,2060,2061],{},"What the CAB approves",[71,2063,2064,2072,2080,2088,2096],{},[55,2065,2066,2069],{},[76,2067,2068],{},"Scope",[76,2070,2071],{},"Same-major JVM security updates only (for example 17.0.x to a later 17.0.x), not major upgrades or vendor swaps",[55,2073,2074,2077],{},[76,2075,2076],{},"Eligible apps",[76,2078,2079],{},"Apps scored into the fast-track tier, with evidence on file",[55,2081,2082,2085],{},[76,2083,2084],{},"Procedure",[76,2086,2087],{},"Progressive rollout, automated health gates, defined rollback",[55,2089,2090,2093],{},[76,2091,2092],{},"Conditions",[76,2094,2095],{},"What forces an app back to normal change: failed gate, score change, incident",[55,2097,2098,2101],{},[76,2099,2100],{},"Review",[76,2102,2103],{},"How often the model and the tier list are re-examined",[12,2105,2106,2107,2110],{},"Major version upgrades and vendor migrations should stay out of the standard change. They carry different risks (see ",[198,2108,2109],{"href":1164},"JVM patch failure modes","), and including them weakens the case for the low-risk category.",[19,2112,2114],{"id":2113},"the-evidence-pack","The evidence pack",[12,2116,2117],{},"Each app in the fast tier should have a record the CAB can inspect at any time, generated from the scoring process rather than written by hand:",[349,2119,2120,2126,2132,2138,2144,2150],{},[30,2121,2122,2125],{},[34,2123,2124],{},"Classification rationale:"," the score, every input behind it, and the threshold it was compared against",[30,2127,2128,2131],{},[34,2129,2130],{},"Named risk acceptor:"," a specific person, their role, and confirmation of their authority, with a timestamp",[30,2133,2134,2137],{},[34,2135,2136],{},"Rollout plan:"," stages, percentages and hold times",[30,2139,2140,2143],{},[34,2141,2142],{},"Health gates:"," the signals checked at each stage and the thresholds that stop the rollout",[30,2145,2146,2149],{},[34,2147,2148],{},"Rollback procedure:"," how to reverse the change, how long it takes, and when it was last rehearsed",[30,2151,2152,2155],{},[34,2153,2154],{},"Rollout evidence:"," for each patch cycle, which gates were checked, the results and the timestamps",[12,2157,2158],{},"The last item is the one that builds trust over time. After a few quarters, the CAB is no longer approving a theory. It's reviewing a track record.",[19,2160,2162],{"id":2161},"re-scoring-keeps-the-tier-honest","Re-scoring keeps the tier honest",[12,2164,2165],{},"Criticality isn't permanent. An internal tool becomes customer-facing. A new data flow brings regulated data into scope. An acquisition doubles an app's user base.",[12,2167,2168],{},"Re-score on a fixed schedule (quarterly is common) and on triggers such as:",[27,2170,2171,2174,2177,2180,2183],{},[30,2172,2173],{},"A significant change in traffic or user base",[30,2175,2176],{},"A new regulated data classification or data flow",[30,2178,2179],{},"An incident involving the application",[30,2181,2182],{},"An M&A event or reorganization that changes ownership",[30,2184,2185],{},"A new critical CVE affecting the app's dependencies",[12,2187,2188,2189,37],{},"Without re-scoring, the classification decays and the CAB's confidence goes with it. Continuous monitoring can raise these triggers automatically; see ",[198,2190,1903],{"href":1902},[19,2192,2194],{"id":2193},"give-people-a-way-to-disagree","Give people a way to disagree",[12,2196,2197],{},"Some app owners will think their tier is wrong in one direction or the other. Provide a defined dispute and escalation path: who reviews it, what evidence they need, and how quickly they respond. Without one, every disagreement turns into an argument outside the process, which is exactly what a CAB doesn't want to see.",[19,2199,2201],{"id":2200},"start-small","Start small",[12,2203,2204],{},"Don't ask for the whole estate at once. Propose a pilot:",[27,2206,2207,2210,2213],{},[30,2208,2209],{},"A few dozen clearly low-criticality applications",[30,2211,2212],{},"One quarterly patch cycle",[30,2214,2215],{},"A report back to the CAB with the rollout evidence, any rollbacks, and the time saved",[12,2217,2218],{},"A successful pilot is the strongest argument for expanding the tier.",[1887,2220,2221],{},[12,2222,2223],{},"Bring the CAB its own data. If the discovery phase shows how many JVMs are running with long-open critical CVEs, the risk of patching slowly is on the table next to the risk of patching fast.",[19,2225,398],{"id":397},[12,2227,2228,2229,2232,2233,2237,2238,37],{},"Our ",[198,2230,2231],{"href":1443},"approach"," describes the classification and governance model we use, and ",[198,2234,2236],{"href":2235},"\u002Fservices\u002Frapid-patch","Rapid Patch"," is the service built on it. If you don't yet know which applications you'd be classifying, start with ",[198,2239,2240],{"href":404},"JVM discovery",{"title":413,"searchDepth":414,"depth":415,"links":2242},[2243,2244,2245,2246,2247,2248,2249,2250,2251],{"id":1959,"depth":414,"text":1960},{"id":1974,"depth":414,"text":1975},{"id":2027,"depth":414,"text":2028},{"id":2041,"depth":414,"text":2042},{"id":2113,"depth":414,"text":2114},{"id":2161,"depth":414,"text":2162},{"id":2193,"depth":414,"text":2194},{"id":2200,"depth":414,"text":2201},{"id":397,"depth":414,"text":398},"risk-governance","2026-08-25","Faster JVM patching is mostly a governance problem. How to score criticality, set thresholds and build the evidence a Change Advisory Board can approve.",{},"\u002Farticles\u002Fcab-approval-for-faster-jvm-patching",{"title":1948,"description":2254},"articles\u002Fcab-approval-for-faster-jvm-patching",[2260,2261,2262,2263,2264],"cab","itil","change-management","risk-classification","governance","QrRxmhrzm_9k3Ga1WdNeg0BoSX_2We7heUVVs-5_Y4E",{"id":2267,"title":2268,"author":7,"body":2269,"category":2675,"date":2676,"description":2677,"draft":431,"extension":432,"featured":431,"image":434,"meta":2678,"navigation":433,"path":381,"readingTime":802,"seo":2679,"stem":2680,"tags":2681,"updated":434,"__hash__":2686},"articles\u002Farticles\u002Ffast-detection-and-rollback-instead-of-regression-testing.md","Fast detection and rollback: a safer alternative to full regression testing",{"type":9,"value":2270,"toc":2662},[2271,2274,2277,2281,2284,2289,2292,2295,2302,2309,2313,2316,2336,2339,2342,2346,2349,2399,2406,2485,2488,2492,2495,2514,2517,2521,2524,2528,2539,2543,2569,2606,2611,2615,2639,2643,2650,2652,2659],[12,2272,2273],{},"Oracle and the OpenJDK update projects ship scheduled security updates four times a year, in January, April, July and October, usually around the third Tuesday of the month. Many enterprises need most of a quarter to get a JVM update through regression testing across their applications. Some never finish before the next one arrives.",[12,2275,2276],{},"For business-critical systems, thorough testing is worth the time. For the long tail of internal tools, batch jobs and low-traffic services, it usually isn't. For that tier there's a better approach than either testing everything or skipping tests.",[19,2278,2280],{"id":2279},"the-argument","The argument",[12,2282,2283],{},"Think about the expected cost of a bad patch reaching production:",[141,2285,2286],{},[12,2287,2288],{},"expected cost ≈ probability of a problem × impact per minute × minutes until it's fixed",[12,2290,2291],{},"Full regression testing attacks the first term, making a problem less likely to ship. Fast detection and fast rollback attack the last term, making any problem that does ship short-lived.",[12,2293,2294],{},"For a same-major JVM security update, such as moving between two 17.0.x releases, the chance of a functional regression is already low. For a low-criticality application the impact per minute is also low. If you can detect a problem in minutes and reverse it in minutes, the expected cost of skipping a multi-week regression cycle is small, and usually much smaller than leaving known CVEs open for another quarter.",[12,2296,2297,2298,2301],{},"That's the core claim: ",[34,2299,2300],{},"when mean time to detect (MTTD) and mean time to recover (MTTR) are low, the value of full pre-deployment regression testing drops sharply."," It holds only if both numbers really are low, so most of the work goes into making them low.",[390,2303,2304],{},[12,2305,2306,2307,37],{},"This approach applies to same-major security updates on applications classified as low-criticality through a documented process. Major version upgrades and vendor swaps carry different risks. See ",[198,2308,2109],{"href":1164},[19,2310,2312],{"id":2311},"progressive-rollout","Progressive rollout",[12,2314,2315],{},"Don't patch everything at once. Roll out in stages, with automated checks between each one:",[349,2317,2318,2324,2330],{},[30,2319,2320,2323],{},[34,2321,2322],{},"Canary (about 1%):"," one instance or a small slice of traffic. Hold long enough to see steady-state behavior, not just startup",[30,2325,2326,2329],{},[34,2327,2328],{},"Partial (about 10%):"," enough traffic that low-frequency errors show up",[30,2331,2332,2335],{},[34,2333,2334],{},"Full (100%):"," complete the rollout, then keep watching through a soak period",[12,2337,2338],{},"Each step is gated. If a gate fails, the rollout stops and rolls back automatically, with no meeting required.",[12,2340,2341],{},"For small applications running on one or two instances, \"1%\" becomes \"one instance first, then the rest.\" The principle is the same: expose the change to real load in a limited way before exposing all of it.",[19,2343,2345],{"id":2344},"what-to-watch-on-a-jvm-change","What to watch on a JVM change",[12,2347,2348],{},"Generic health checks, like \"is the process up?\", miss most JVM-specific regressions. Compare the patched instances against the unpatched baseline on these signals:",[27,2350,2351,2357,2363,2369,2375,2381,2387,2393],{},[30,2352,2353,2356],{},[34,2354,2355],{},"Error rate:"," HTTP 5xx, exception counts, failed jobs",[30,2358,2359,2362],{},[34,2360,2361],{},"Latency:"," p50 and p99, since JVM changes often affect the tail first",[30,2364,2365,2368],{},[34,2366,2367],{},"GC behavior:"," pause time, pause frequency and collection counts",[30,2370,2371,2374],{},[34,2372,2373],{},"Memory:"," heap after GC, metaspace and native memory where you can measure it",[30,2376,2377,2380],{},[34,2378,2379],{},"Threads:"," thread counts and blocked threads",[30,2382,2383,2386],{},[34,2384,2385],{},"Warm-up:"," time to reach steady-state latency after start",[30,2388,2389,2392],{},[34,2390,2391],{},"TLS:"," handshake failures to downstream systems, which point to protocol or cipher changes",[30,2394,2395,2398],{},[34,2396,2397],{},"Agent health:"," whether APM and security agents attached and are reporting",[12,2400,2401,2402,2405],{},"Example gates might look like this. The thresholds are ",[34,2403,2404],{},"illustrative only"," and should be tuned to each application's normal variance:",[49,2407,2408,2421],{},[52,2409,2410],{},[55,2411,2412,2415,2418],{},[58,2413,2414],{},"Signal",[58,2416,2417],{},"Compared against",[58,2419,2420],{},"Example gate",[71,2422,2423,2434,2444,2454,2464,2475],{},[55,2424,2425,2428,2431],{},[76,2426,2427],{},"Error rate",[76,2429,2430],{},"Unpatched baseline",[76,2432,2433],{},"Fail if more than 1.5× baseline over 10 minutes",[55,2435,2436,2439,2441],{},[76,2437,2438],{},"p99 latency",[76,2440,2430],{},[76,2442,2443],{},"Fail if more than 20% higher over 15 minutes",[55,2445,2446,2449,2451],{},[76,2447,2448],{},"GC pause time (p99)",[76,2450,2430],{},[76,2452,2453],{},"Fail if more than 50% higher",[55,2455,2456,2459,2461],{},[76,2457,2458],{},"Heap after GC",[76,2460,2430],{},[76,2462,2463],{},"Flag a steady upward trend across the hold period",[55,2465,2466,2469,2472],{},[76,2467,2468],{},"TLS handshake failures",[76,2470,2471],{},"Absolute",[76,2473,2474],{},"Fail on any sustained increase",[55,2476,2477,2480,2482],{},[76,2478,2479],{},"APM agent reporting",[76,2481,2471],{},[76,2483,2484],{},"Fail if the agent stops reporting",[12,2486,2487],{},"Comparing against a live unpatched baseline, rather than fixed numbers, removes most false alarms caused by normal traffic swings.",[19,2489,2491],{"id":2490},"smoke-tests-and-synthetic-transactions","Smoke tests and synthetic transactions",[12,2493,2494],{},"Replace the full regression suite with a small set of checks that exercise what matters:",[27,2496,2497,2502,2508],{},[30,2498,2499,2501],{},[34,2500,1142],{}," run right after each instance starts: does the app start, connect to its database and queue, and serve its health endpoint?",[30,2503,2504,2507],{},[34,2505,2506],{},"Synthetic transactions"," run continuously: scripted logins, searches, report generations, or whatever the app's two or three core paths are",[30,2509,2510,2513],{},[34,2511,2512],{},"Integration probes"," hit each external dependency, which is especially useful for catching TLS problems",[12,2515,2516],{},"These run in minutes, can be kept current easily, and exercise the code paths a JVM change is most likely to disturb.",[19,2518,2520],{"id":2519},"making-rollback-fast","Making rollback fast",[12,2522,2523],{},"Fast rollback is often the actual gap. In many enterprise estates, particularly outside containers, reverting a JVM means a manual change, a ticket and a wait. Fix that first. Without it, none of the above is safe.",[187,2525,2527],{"id":2526},"in-containerized-environments","In containerized environments",[27,2529,2530,2533,2536],{},[30,2531,2532],{},"Treat images as immutable and version them. Rolling back means redeploying the previous image tag",[30,2534,2535],{},"Keep the previous image available and tested until the soak period ends",[30,2537,2538],{},"Have the deployment tooling perform the rollback automatically when a gate fails",[187,2540,2542],{"id":2541},"on-vms-and-bare-metal","On VMs and bare metal",[27,2544,2545,2551,2557,2563],{},[30,2546,2547,2550],{},[34,2548,2549],{},"Install side by side."," Put the new JDK in its own versioned directory and switch the application to it using a symlink, environment variable or service configuration. Don't overwrite the old one",[30,2552,2553,2556],{},[34,2554,2555],{},"Don't uninstall the previous runtime"," until the soak period has passed",[30,2558,2559,2562],{},[34,2560,2561],{},"Script the switch"," in both directions, and make sure the application restarts cleanly with either runtime",[30,2564,2565,2568],{},[34,2566,2567],{},"Rehearse it."," A rollback nobody has run is a hypothesis, not a procedure",[1482,2570,2572],{"className":1484,"code":2571,"language":1486,"meta":413,"style":413},"# Illustrative side-by-side layout on a Linux host\n\u002Fopt\u002Fjava\u002Fjdk-17.0.15\u002F\n\u002Fopt\u002Fjava\u002Fjdk-17.0.16\u002F\n\u002Fopt\u002Fjava\u002Fcurrent -> \u002Fopt\u002Fjava\u002Fjdk-17.0.16   # rollback = repoint and restart\n",[1029,2573,2574,2579,2584,2589],{"__ignoreMap":413},[1490,2575,2576],{"class":1492,"line":1493},[1490,2577,2578],{"class":1496},"# Illustrative side-by-side layout on a Linux host\n",[1490,2580,2581],{"class":1492,"line":414},[1490,2582,2583],{"class":1517},"\u002Fopt\u002Fjava\u002Fjdk-17.0.15\u002F\n",[1490,2585,2586],{"class":1492,"line":415},[1490,2587,2588],{"class":1517},"\u002Fopt\u002Fjava\u002Fjdk-17.0.16\u002F\n",[1490,2590,2591,2594,2597,2600,2603],{"class":1492,"line":1578},[1490,2592,2593],{"class":1517},"\u002Fopt\u002Fjava\u002Fcurrent",[1490,2595,2596],{"class":1506}," -",[1490,2598,2599],{"class":1540},">",[1490,2601,2602],{"class":1525}," \u002Fopt\u002Fjava\u002Fjdk-17.0.16",[1490,2604,2605],{"class":1496},"   # rollback = repoint and restart\n",[177,2607,2608],{},[12,2609,2610],{},"If rolling back a JVM on a given application takes hours, that application isn't ready for reduced pre-deployment testing yet, whatever its criticality score. Make rollback fast first.",[19,2612,2614],{"id":2613},"where-this-doesnt-apply","Where this doesn't apply",[27,2616,2617,2627,2633],{},[30,2618,2619,2622,2623],{},[34,2620,2621],{},"Business-critical applications:"," keep rigorous testing and make it faster with risk-based test selection and shadow traffic. See ",[198,2624,2626],{"href":2625},"\u002Fservices\u002Fcritical-patch-assurance","Critical Patch Assurance",[30,2628,2629,2632],{},[34,2630,2631],{},"Major version upgrades:"," removed APIs and changed defaults need targeted assessment before any rollout",[30,2634,2635,2638],{},[34,2636,2637],{},"Apps without observability:"," if you can't see errors and latency, you can't gate on them",[19,2640,2642],{"id":2641},"getting-it-approved","Getting it approved",[12,2644,2645,2646,2649],{},"The technical case is only half the work. A Change Advisory Board also has to accept the process. Our guide to ",[198,2647,2648],{"href":2256},"getting faster JVM patching past the CAB"," covers classification, the standard change model and the evidence to keep.",[19,2651,398],{"id":397},[12,2653,2654,2656,2657,37],{},[198,2655,2236],{"href":2235}," is our service built on this model, including fixing rollback where it's missing. The full method is described in ",[198,2658,1444],{"href":1443},[1906,2660,2661],{},"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 .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}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":413,"searchDepth":414,"depth":415,"links":2663},[2664,2665,2666,2667,2668,2672,2673,2674],{"id":2279,"depth":414,"text":2280},{"id":2311,"depth":414,"text":2312},{"id":2344,"depth":414,"text":2345},{"id":2490,"depth":414,"text":2491},{"id":2519,"depth":414,"text":2520,"children":2669},[2670,2671],{"id":2526,"depth":415,"text":2527},{"id":2541,"depth":415,"text":2542},{"id":2613,"depth":414,"text":2614},{"id":2641,"depth":414,"text":2642},{"id":397,"depth":414,"text":398},"patch-management","2026-08-18","For low-criticality apps, quick detection and cheap rollback cut JVM patch risk more than a full regression run. Here's how to build that safety net.",{},{"title":2268,"description":2677},"articles\u002Ffast-detection-and-rollback-instead-of-regression-testing",[2311,2682,2683,2684,2685],"rollback","observability","canary","patch-cadence","x601uJ3l6gvr8R_-xeLIFcM-IUG414z9IKmZwMgoqTE",{"id":2688,"title":2689,"author":7,"body":2690,"category":2675,"date":3104,"description":3105,"draft":431,"extension":432,"featured":431,"image":434,"meta":3106,"navigation":433,"path":1164,"readingTime":437,"seo":3107,"stem":3108,"tags":3109,"updated":434,"__hash__":3116},"articles\u002Farticles\u002Fjvm-patch-failure-modes.md","Six ways JVM changes break production, and how to see them coming",{"type":9,"value":2691,"toc":3093},[2692,2695,2698,2702,2792,2797,2801,2808,2814,2819,2833,2839,2843,2846,2851,2855,2866,2875,2879,2882,2887,2892,2897,2901,2904,2909,2913,2924,2929,2933,2936,2966,2983,3000,3009,3013,3016,3021,3026,3038,3042,3045,3071,3080,3082],[12,2693,2694],{},"When a JVM change breaks something in production, it rarely fails in a new way. Most incidents fall into a short list of patterns that repeat across organizations and releases. If you know the list, you can check for each item before rollout instead of discovering it afterwards.",[12,2696,2697],{},"First, though, it matters what kind of change you're making.",[19,2699,2701],{"id":2700},"not-every-jvm-patch-carries-the-same-risk","Not every \"JVM patch\" carries the same risk",[49,2703,2704,2720],{},[52,2705,2706],{},[55,2707,2708,2711,2714,2717],{},[58,2709,2710],{},"Failure mode",[58,2712,2713],{},"Same-major security update (e.g. 17.0.x → 17.0.y)",[58,2715,2716],{},"Major version upgrade (e.g. 11 → 17 → 21)",[58,2718,2719],{},"Vendor swap, same version (e.g. Oracle JDK → Temurin)",[71,2721,2722,2735,2747,2758,2769,2780],{},[55,2723,2724,2727,2730,2733],{},[76,2725,2726],{},"APM and instrumentation agents",[76,2728,2729],{},"Occasionally",[76,2731,2732],{},"Frequently",[76,2734,2729],{},[55,2736,2737,2740,2742,2744],{},[76,2738,2739],{},"TLS and cipher defaults",[76,2741,2729],{},[76,2743,2732],{},[76,2745,2746],{},"Rarely",[55,2748,2749,2752,2754,2756],{},[76,2750,2751],{},"JIT and warm-up behavior",[76,2753,2746],{},[76,2755,2729],{},[76,2757,2746],{},[55,2759,2760,2763,2765,2767],{},[76,2761,2762],{},"GC defaults and flags",[76,2764,2746],{},[76,2766,2732],{},[76,2768,2746],{},[55,2770,2771,2774,2776,2778],{},[76,2772,2773],{},"Removed APIs and encapsulation",[76,2775,321],{},[76,2777,2732],{},[76,2779,321],{},[55,2781,2782,2785,2788,2790],{},[76,2783,2784],{},"Container awareness",[76,2786,2787],{},"Only on very old builds",[76,2789,2729],{},[76,2791,2787],{},[12,2793,2794,2795,1445],{},"The frequencies are our qualitative judgment, not measured rates. The pattern is what matters: same-major security updates are low-risk, and most serious breakage comes with major upgrades. That's why they should be planned and governed differently (see ",[198,2796,1444],{"href":1443},[19,2798,2800],{"id":2799},"_1-apm-and-instrumentation-agents","1. APM and instrumentation agents",[12,2802,2803,2804,2807],{},"APM, security and profiling tools usually attach to the JVM as Java agents (",[1029,2805,2806],{},"-javaagent",") and rewrite bytecode as classes load. To do that they have to understand the class file format and, often, parts of the JDK's internals.",[12,2809,2810,2813],{},[34,2811,2812],{},"Symptom:"," The application fails to start, logs errors from the agent, or runs normally while the agent silently stops reporting. On major upgrades, an older agent may simply not support the newer class file version.",[12,2815,2816],{},[34,2817,2818],{},"Detect before rollout:",[27,2820,2821,2827,2830],{},[30,2822,2823,2824],{},"Inventory which agents, and which versions, are attached to each JVM. Check the startup command line and environment variables such as ",[1029,2825,2826],{},"JAVA_TOOL_OPTIONS",[30,2828,2829],{},"Check each vendor's supported-JDK matrix for the target version",[30,2831,2832],{},"In the canary stage, gate on \"the agent is reporting,\" not just \"the app is up\"",[12,2834,2835,2838],{},[34,2836,2837],{},"Mitigate:"," Upgrade the agent before, or together with, the JVM. For major upgrades, test the agent on the target JDK first.",[19,2840,2842],{"id":2841},"_2-tls-and-cipher-suite-defaults","2. TLS and cipher suite defaults",[12,2844,2845],{},"JDK updates regularly tighten security defaults: disabling old protocol versions, removing weak cipher suites, and distrusting certain root certificates. A notable example: TLS 1.0 and 1.1 were disabled by default across supported Java releases in the April 2021 updates.",[12,2847,2848,2850],{},[34,2849,2812],{}," Handshake failures when connecting to older partners, appliances, databases, mainframe gateways or internal services still using old protocols or ciphers. These often appear only in specific integrations, which is why they slip through generic testing.",[12,2852,2853],{},[34,2854,2818],{},[27,2856,2857,2860,2863],{},[30,2858,2859],{},"Read the release notes for security-default changes. They're usually listed explicitly",[30,2861,2862],{},"Inventory the outbound TLS endpoints each application talks to, and test handshakes against them from a patched JVM",[30,2864,2865],{},"Watch handshake failure rates during the canary stage",[12,2867,2868,2870,2871,2874],{},[34,2869,2837],{}," Fix the far end where you can. Re-enabling a disabled protocol in ",[1029,2872,2873],{},"java.security"," is sometimes necessary as a stopgap. Make it a documented, time-limited exception, not a silent config change.",[19,2876,2878],{"id":2877},"_3-jit-compilation-and-warm-up","3. JIT compilation and warm-up",[12,2880,2881],{},"The JIT compiler improves between releases, but \"different\" isn't always \"better\" for every workload. Changes in inlining, compilation thresholds or tiered compilation can shift how quickly an application reaches steady-state performance.",[12,2883,2884,2886],{},[34,2885,2812],{}," Higher latency for the first minutes after startup, or a changed p99 on latency-sensitive services. Startup-time SLOs and autoscaling behavior are affected first.",[12,2888,2889,2891],{},[34,2890,2818],{}," Measure time-to-steady-state and tail latency on a canary under real traffic, not only in a quiet test environment.",[12,2893,2894,2896],{},[34,2895,2837],{}," Usually no action is needed for same-major updates. For latency-critical services on major upgrades, plan a performance check and consider warm-up traffic before instances join the load balancer.",[19,2898,2900],{"id":2899},"_4-gc-defaults-and-tuning-flags","4. GC defaults and tuning flags",[12,2902,2903],{},"Garbage collector defaults and options change across major versions. G1 has been the default collector since JDK 9. The CMS collector was deprecated in JDK 9 and removed in JDK 14. Many tuning flags accumulated over years of Java 8 operations are deprecated, ignored or rejected on newer releases.",[12,2905,2906,2908],{},[34,2907,2812],{}," The JVM refuses to start because of an unrecognized option, or it starts and ignores a flag, changing memory and pause behavior. Pause times, heap usage or throughput shift after the upgrade.",[12,2910,2911],{},[34,2912,2818],{},[27,2914,2915,2918,2921],{},[30,2916,2917],{},"Collect the actual JVM flags from every instance during discovery, not just from documentation",[30,2919,2920],{},"Validate flags against the target version before rollout",[30,2922,2923],{},"Compare GC pause time and frequency between canary and baseline",[12,2925,2926,2928],{},[34,2927,2837],{}," Clean up flags as part of the upgrade. For most applications on modern JDKs, fewer hand-tuned GC flags is better than carrying old ones forward.",[19,2930,2932],{"id":2931},"_5-removed-apis-and-strong-encapsulation","5. Removed APIs and strong encapsulation",[12,2934,2935],{},"This is the main source of breakage on major upgrades. Examples:",[27,2937,2938,2948,2954,2960],{},[30,2939,2940,2943,2944,2947],{},[34,2941,2942],{},"Strong encapsulation of JDK internals:"," JDK 16 (JEP 396) enabled strong encapsulation by default, and JDK 17 (JEP 403) removed the command-line option that relaxed it globally. Libraries that reached into ",[1029,2945,2946],{},"sun.*"," and other internal packages via reflection can fail",[30,2949,2950,2953],{},[34,2951,2952],{},"The Security Manager:"," deprecated for removal in JDK 17 (JEP 411) and permanently disabled in JDK 24 (JEP 486). Applications and frameworks that rely on it need a different approach",[30,2955,2956,2959],{},[34,2957,2958],{},"The Nashorn JavaScript engine:"," removed in JDK 15. Applications that evaluated JavaScript through the scripting API need a replacement",[30,2961,2962,2965],{},[34,2963,2964],{},"Java EE modules"," such as JAXB and JAX-WS were removed from the JDK in JDK 11 and must now be added as explicit dependencies",[12,2967,2968,2970,2971,2974,2975,2978,2979,2982],{},[34,2969,2812],{}," ",[1029,2972,2973],{},"InaccessibleObjectException",", ",[1029,2976,2977],{},"ClassNotFoundException"," or ",[1029,2980,2981],{},"NoSuchMethodError"," at startup or, worse, only on a rarely used code path.",[12,2984,2985,2987,2988,2991,2992,2995,2996,2999],{},[34,2986,2818],{}," Static analysis finds most of this before anyone patches anything. The JDK's own ",[1029,2989,2990],{},"jdeps"," tool (including ",[1029,2993,2994],{},"jdeps --jdk-internals",") reports use of internal APIs, and ",[1029,2997,2998],{},"jdeprscan"," reports use of deprecated APIs. Check library versions against their documented JDK support.",[12,3001,3002,3004,3005,3008],{},[34,3003,2837],{}," Upgrade the offending libraries. Use targeted ",[1029,3006,3007],{},"--add-opens"," flags only as a documented, temporary exception.",[19,3010,3012],{"id":3011},"_6-container-awareness","6. Container awareness",[12,3014,3015],{},"Early Java 8 builds sized the heap and thread pools from the host's resources, not the container's CPU and memory limits. Proper container support arrived in JDK 10 and was backported to Java 8 in update 191 (8u191).",[12,3017,3018,3020],{},[34,3019,2812],{}," Containers killed for exceeding memory limits, or JVMs using far more GC and compiler threads than the container has CPUs.",[12,3022,3023,3025],{},[34,3024,2818],{}," Discovery should flag any Java 8 runtime older than 8u191 running in a container. These are also, almost by definition, badly out of date on security patches.",[12,3027,3028,3030,3031,3034,3035,37],{},[34,3029,2837],{}," Update the runtime. Then review any hard-coded ",[1029,3032,3033],{},"-Xmx"," values set as a workaround, and prefer percentage-based sizing such as ",[1029,3036,3037],{},"-XX:MaxRAMPercentage",[19,3039,3041],{"id":3040},"turning-the-list-into-a-checklist","Turning the list into a checklist",[12,3043,3044],{},"For each application, before a JVM change:",[349,3046,3047,3050,3053,3056,3059,3068],{},[30,3048,3049],{},"Which agents are attached, and do they support the target version?",[30,3051,3052],{},"What outbound TLS endpoints does it use, and do they work against the new defaults?",[30,3054,3055],{},"Is it latency-sensitive enough to need a warm-up check?",[30,3057,3058],{},"Which JVM flags are set, and are they all valid on the target?",[30,3060,3061,3062,3064,3065,3067],{},"For major upgrades: what do ",[1029,3063,2990],{}," and ",[1029,3066,2998],{}," report?",[30,3069,3070],{},"If containerized: is the runtime container-aware?",[12,3072,3073,3074,3076,3077,37],{},"Most of these questions are answered by a good inventory. See ",[198,3075,360],{"href":359},". The rest are covered by canary gates, described in ",[198,3078,3079],{"href":381},"fast detection and rollback",[19,3081,398],{"id":397},[12,3083,3084,3085,3087,3088,3090,3091,37],{},"For same-major security updates on low-criticality apps, ",[198,3086,2236],{"href":2235}," builds these checks into the rollout. For business-critical systems and major upgrades, ",[198,3089,2626],{"href":2625}," includes a readiness assessment that runs this analysis before any patch is attempted. If you're also changing vendors, see the ",[198,3092,248],{"href":247},{"title":413,"searchDepth":414,"depth":415,"links":3094},[3095,3096,3097,3098,3099,3100,3101,3102,3103],{"id":2700,"depth":414,"text":2701},{"id":2799,"depth":414,"text":2800},{"id":2841,"depth":414,"text":2842},{"id":2877,"depth":414,"text":2878},{"id":2899,"depth":414,"text":2900},{"id":2931,"depth":414,"text":2932},{"id":3011,"depth":414,"text":3012},{"id":3040,"depth":414,"text":3041},{"id":397,"depth":414,"text":398},"2026-08-11","APM agents, TLS defaults, JIT warm-up, GC changes, removed APIs and container awareness: how each JVM failure mode shows up, and how to catch it before rollout.",{},{"title":2689,"description":3105},"articles\u002Fjvm-patch-failure-modes",[3110,3111,3112,3113,3114,3115],"jvm-upgrade","failure-modes","tls","garbage-collection","java-agents","testing","7D2YYirroTkpbNNavdjU7NPhnH4Gov_4WWffi-fboDg",{"id":3118,"title":3119,"author":7,"body":3120,"category":3495,"date":3496,"description":3497,"draft":431,"extension":432,"featured":431,"image":434,"meta":3498,"navigation":433,"path":704,"readingTime":802,"seo":3499,"stem":3500,"tags":3501,"updated":434,"__hash__":3505},"articles\u002Farticles\u002Fpatching-jvms-inside-vendor-products.md","Patching the JVMs you didn't install: Java inside vendor products",{"type":9,"value":3121,"toc":3481},[3122,3125,3128,3132,3135,3185,3188,3192,3200,3217,3220,3249,3253,3259,3262,3323,3334,3338,3342,3345,3349,3352,3356,3359,3385,3391,3395,3398,3416,3420,3423,3430,3433,3442,3447,3451,3454,3468,3470],[12,3123,3124],{},"When security teams talk about \"patching Java,\" they usually mean the JDKs their own engineers install: the runtime on the standard server build, the base container image, the app-server installation. Those matter, and they're the easy part.",[12,3126,3127],{},"The harder part is the Java that arrived inside something else. A large share of the JVMs in a typical enterprise were never installed as Java at all. They came bundled inside a commercial product, an appliance, a build tool or a desktop application, each with its own runtime, update schedule and support rules.",[19,3129,3131],{"id":3130},"where-bundled-jvms-hide","Where bundled JVMs hide",[12,3133,3134],{},"Common places we find private Java runtimes:",[27,3136,3137,3143,3149,3155,3161,3167,3173,3179],{},[30,3138,3139,3142],{},[34,3140,3141],{},"Application servers and middleware"," installed from vendor media, which often include their own JDK.",[30,3144,3145,3148],{},[34,3146,3147],{},"Database and data-platform tooling",": management consoles, client tools, ETL and integration products.",[30,3150,3151,3154],{},[34,3152,3153],{},"Search and analytics engines."," Some ship with a bundled JDK by default. Elasticsearch is a well-known example.",[30,3156,3157,3160],{},[34,3158,3159],{},"CI\u002FCD and developer tooling",": build agents, artifact repositories and IDEs that bundle their own runtime.",[30,3162,3163,3166],{},[34,3164,3165],{},"Monitoring, backup and security products",": collectors, agents and management servers.",[30,3168,3169,3172],{},[34,3170,3171],{},"Collaboration and ticketing platforms"," whose installers include a JRE.",[30,3174,3175,3178],{},[34,3176,3177],{},"Network and storage appliances",", virtual or physical, with management interfaces written in Java.",[30,3180,3181,3184],{},[34,3182,3183],{},"Desktop applications"," that bundle a private JRE to avoid depending on the system Java.",[12,3186,3187],{},"Each of these has a runtime that's often several updates behind, sometimes a full major version behind, and owned in practice by nobody.",[19,3189,3191],{"id":3190},"why-your-scanners-miss-them","Why your scanners miss them",[12,3193,3194,3195,1100,3197,3199],{},"Most inventory and vulnerability tools find Java by asking the operating system: the package manager, the Windows installed-programs list, or the ",[1029,3196,1099],{},[1029,3198,1103],{},". Bundled runtimes usually bypass all three:",[27,3201,3202,3205,3211,3214],{},[30,3203,3204],{},"They're unpacked into the product's own directory, not installed as a package.",[30,3206,3207,3208,3210],{},"They're not on the ",[1029,3209,1103],{},", because only the product's launcher uses them.",[30,3212,3213],{},"Their version may not appear in any registry or package database.",[30,3215,3216],{},"In containers, the JDK is a layer inside a vendor image you pull, not something you install.",[12,3218,3219],{},"Some scanners do file-system or running-process checks and catch more. Even then, results are often reported as \"Java vulnerability on host X\" with no link to the product that owns the runtime. That leaves the ticket with nowhere useful to go.",[12,3221,3222,3223,3226,3227,3230,3231,3233,3234,3064,3237,3239,3240,3064,3243,3246,3247,37],{},"Good discovery looks at ",[34,3224,3225],{},"running processes",", the ",[34,3228,3229],{},"file system"," (for ",[1029,3232,1476],{}," files, ",[1029,3235,3236],{},"libjvm",[1029,3238,1099],{}," binaries outside standard locations), ",[34,3241,3242],{},"container images",[34,3244,3245],{},"artifact repositories",". It then ties each runtime back to the product and owner responsible for it. We describe that approach in ",[198,3248,360],{"href":359},[19,3250,3252],{"id":3251},"the-supportability-question","The supportability question",[12,3254,3255,3256],{},"Once you've found an outdated bundled runtime, the obvious fix is to replace it with a patched JDK. Before you do, ask: ",[34,3257,3258],{},"will the vendor still support the product if you do?",[12,3260,3261],{},"Vendors fall into roughly four groups:",[49,3263,3264,3277],{},[52,3265,3266],{},[55,3267,3268,3271,3274],{},[58,3269,3270],{},"Vendor position",[58,3272,3273],{},"What it means",[58,3275,3276],{},"Typical action",[71,3278,3279,3290,3301,3312],{},[55,3280,3281,3284,3287],{},[76,3282,3283],{},"Ships runtime updates with product patches",[76,3285,3286],{},"The JVM is patched when you patch the product",[76,3288,3289],{},"Keep the product current; track the lag between Java CPUs and vendor releases",[55,3291,3292,3295,3298],{},[76,3293,3294],{},"Documents a supported JRE swap",[76,3296,3297],{},"You may point the product at a newer JDK within stated limits",[76,3299,3300],{},"Swap within the certified versions; keep evidence of the support statement",[55,3302,3303,3306,3309],{},[76,3304,3305],{},"Certifies specific versions only",[76,3307,3308],{},"Other runtimes may work but are unsupported",[76,3310,3311],{},"Ask for an updated certification; weigh the risk of running unsupported",[55,3313,3314,3317,3320],{},[76,3315,3316],{},"Silent or refuses",[76,3318,3319],{},"No guidance, or runtime changes void support",[76,3321,3322],{},"Use compensating controls and escalate commercially",[12,3324,3325,3326,3329,3330,3333],{},"Check the product's ",[34,3327,3328],{},"certification matrix"," or supported-platforms documentation. Where it's silent, ask the vendor directly and ",[34,3331,3332],{},"get the answer in writing",". \"Support told us on a call that it's fine\" won't help much when an incident review asks why the runtime was changed.",[19,3335,3337],{"id":3336},"your-options-in-order-of-preference","Your options, in order of preference",[187,3339,3341],{"id":3340},"_1-take-the-vendors-update","1. Take the vendor's update",[12,3343,3344],{},"If the vendor ships the patched runtime as part of a product release, upgrading the product is the supported path. Measure how long the vendor takes to ship Java CPU fixes. A vendor that routinely lags two or three quarters behind the Java security schedule is a risk worth raising at renewal.",[187,3346,3348],{"id":3347},"_2-do-a-supported-runtime-replacement","2. Do a supported runtime replacement",[12,3350,3351],{},"If the vendor documents how to use an external or newer JDK, do it within those limits. Treat it like any other JVM patch: smoke test, canary where possible and keep a rollback. Remember that the product's next upgrade may silently restore its bundled runtime, so re-check after every product update.",[187,3353,3355],{"id":3354},"_3-apply-compensating-controls","3. Apply compensating controls",[12,3357,3358],{},"When you can't patch the runtime without losing support, reduce the exposure instead:",[27,3360,3361,3367,3373,3379],{},[30,3362,3363,3366],{},[34,3364,3365],{},"Network isolation."," Restrict who and what can reach the product, especially management interfaces.",[30,3368,3369,3372],{},[34,3370,3371],{},"Disable unused features"," that expose vulnerable code paths, such as remote management, deserialization endpoints or unused protocols.",[30,3374,3375,3378],{},[34,3376,3377],{},"Tighten TLS and authentication"," at a proxy or load balancer in front of the product.",[30,3380,3381,3384],{},[34,3382,3383],{},"Increase monitoring"," on the host, and document the accepted risk with a named owner and a review date.",[12,3386,3387,3388,37],{},"Compensating controls are a legitimate risk decision, but they should be recorded as one, not left as an undocumented exception. The governance side is covered in ",[198,3389,3390],{"href":2256},"getting faster JVM patching approved by your CAB",[187,3392,3394],{"id":3393},"_4-use-commercial-pressure","4. Use commercial pressure",[12,3396,3397],{},"Vendors respond to contract terms more reliably than to support tickets. At renewal or in new contracts, consider asking for:",[27,3399,3400,3403,3410,3413],{},[30,3401,3402],{},"A commitment to ship Java security updates within a defined window after each quarterly CPU.",[30,3404,3405,3406,3409],{},"A ",[34,3407,3408],{},"software bill of materials (SBOM)"," that lists the bundled runtime, version and vendor.",[30,3411,3412],{},"A documented, supported procedure for replacing the bundled runtime.",[30,3414,3415],{},"Support for current LTS Java releases within a reasonable period after release.",[19,3417,3419],{"id":3418},"the-oracle-licensing-nuance","The Oracle licensing nuance",[12,3421,3422],{},"Bundled runtimes also complicate Oracle Java licensing, in both directions.",[12,3424,3425,3426,3429],{},"Some commercial products, including some Oracle products and some third-party products, include a Java SE license that's ",[34,3427,3428],{},"restricted to running that product",". An Oracle JDK bundled that way may not create exposure by itself, but it generally doesn't allow general-purpose use by other applications on the same machine.",[12,3431,3432],{},"The opposite also happens. A product may have been installed with an Oracle JDK that someone downloaded separately, with no licensing coverage from the product vendor at all.",[12,3434,3435,3436,3438,3439,37],{},"So don't assume either way. For each bundled Oracle runtime, check the product's license terms and record the conclusion. This matters because of ",[198,3437,201],{"href":200},": one uncovered install can put the whole organization in scope. For the timing pressure on JDK 21 in particular, see ",[198,3440,3441],{"href":436},"what the end of the free update window means",[390,3443,3444],{},[12,3445,3446],{},"Licensing conclusions depend on specific contract wording. This article is not legal advice. Confirm with your licensing team and the product vendor.",[19,3448,3450],{"id":3449},"making-it-sustainable","Making it sustainable",[12,3452,3453],{},"Bundled runtimes don't stay fixed. Products get upgraded, reinstalled and replaced, and each change can bring a different runtime. The practical approach:",[349,3455,3456,3459,3462,3465],{},[30,3457,3458],{},"Keep the inventory of bundled runtimes linked to products and owners.",[30,3460,3461],{},"Track each product's Java update lag against the quarterly CPU calendar.",[30,3463,3464],{},"Record the support position and license position per product.",[30,3466,3467],{},"Re-scan continuously, not once a year, so a product upgrade that restores an old runtime gets noticed.",[19,3469,398],{"id":397},[12,3471,2228,3472,3476,3477,3480],{},[198,3473,3475],{"href":3474},"\u002Fservices\u002Fthird-party-applications","third-party application advisory"," works through bundled runtimes product by product, from support position to vendor escalation. ",[198,3478,3479],{"href":1902},"Continuous drift monitoring"," catches it when a product upgrade quietly brings an old JVM back.",{"title":413,"searchDepth":414,"depth":415,"links":3482},[3483,3484,3485,3486,3492,3493,3494],{"id":3130,"depth":414,"text":3131},{"id":3190,"depth":414,"text":3191},{"id":3251,"depth":414,"text":3252},{"id":3336,"depth":414,"text":3337,"children":3487},[3488,3489,3490,3491],{"id":3340,"depth":415,"text":3341},{"id":3347,"depth":415,"text":3348},{"id":3354,"depth":415,"text":3355},{"id":3393,"depth":415,"text":3394},{"id":3418,"depth":414,"text":3419},{"id":3449,"depth":414,"text":3450},{"id":397,"depth":414,"text":398},"third-party-apps","2026-08-04","Many commercial products ship their own Java runtime. Why scanners miss them, what vendors will support, and how to handle the ones you can't patch yourself.",{},{"title":3119,"description":3497},"articles\u002Fpatching-jvms-inside-vendor-products",[3495,3502,1940,3503,3504],"vendor-management","patching","sbom","evxCmQkEaWsBhnvnceMe-gfG8-h4zN5-9uZZdsr7ioM",[3507,3728,3845,3957,4056,4141],{"id":3508,"title":3509,"body":3510,"category":1933,"description":3714,"engagement":3715,"extension":432,"headline":3716,"icon":3717,"meta":3718,"navigation":433,"order":1493,"outcomes":3719,"path":404,"seo":3725,"stem":3726,"__hash__":3727},"services\u002Fservices\u002Fjvm-discovery.md","JVM Discovery & Estate Assessment",{"type":9,"value":3511,"toc":3707},[3512,3516,3523,3526,3530,3533,3574,3578,3587,3618,3622,3691,3695],[19,3513,3515],{"id":3514},"the-problem","The problem",[12,3517,3518,3519,3522],{},"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 ",[34,3520,3521],{},"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\".",[12,3524,3525],{},"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.",[19,3527,3529],{"id":3528},"what-we-find","What we find",[12,3531,3532],{},"For every JVM across dev, staging and production we capture:",[27,3534,3535,3541,3547,3553,3558,3564],{},[30,3536,3537,3540],{},[34,3538,3539],{},"Version, vendor and patch level",": Oracle JDK, Eclipse Temurin, Amazon Corretto, Azul Zulu, Red Hat, Microsoft, IBM Semeru and others",[30,3542,3543,3546],{},[34,3544,3545],{},"Where it is embedded",": standalone apps, Tomcat, WebLogic, WebSphere, JBoss\u002FWildFly, vendor products, containers",[30,3548,3549,3552],{},[34,3550,3551],{},"CVE exposure",", mapped to each version and scored so the worst exposure rises to the top",[30,3554,3555,3557],{},[34,3556,1423],{},": APM, security and profiling agents, which cause many patch failures",[30,3559,3560,3563],{},[34,3561,3562],{},"Ownership",": who actually runs each application. This is often the hardest part to get right.",[30,3565,3566,3569,3570],{},[34,3567,3568],{},"Criticality signals"," that feed ",[198,3571,3573],{"href":3572},"\u002Fapproach#classification","application classification",[19,3575,3577],{"id":3576},"how-we-do-it","How we do it",[390,3579,3580],{},[12,3581,3582,3583,3586],{},"Discovery is ",[34,3584,3585],{},"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.",[27,3588,3589,3595,3601,3606,3612],{},[30,3590,3591,3594],{},[34,3592,3593],{},"Agentless scanning"," over SSH and WinRM (process listings and filesystem inspection) where possible",[30,3596,3597,3600],{},[34,3598,3599],{},"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.",[30,3602,3603,3605],{},[34,3604,1792],{}," (AWS, Azure, GCP) for instance and container metadata",[30,3607,3608,3611],{},[34,3609,3610],{},"Container image and artifact repository scanning"," (registries, Nexus, Artifactory) to catch JVMs before they are even running",[30,3613,3614,3617],{},[34,3615,3616],{},"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.",[19,3619,3621],{"id":3620},"three-ways-to-engage","Three ways to engage",[49,3623,3624,3639],{},[52,3625,3626],{},[55,3627,3628,3631,3633,3636],{},[58,3629,3630],{},"Package",[58,3632,2068],{},[58,3634,3635],{},"Turnaround",[58,3637,3638],{},"Purpose",[71,3640,3641,3657,3673],{},[55,3642,3643,3648,3651,3654],{},[76,3644,3645],{},[34,3646,3647],{},"Quick Scan",[76,3649,3650],{},"One business unit or subset of the estate",[76,3652,3653],{},"Days",[76,3655,3656],{},"Prove what a full assessment will find",[55,3658,3659,3664,3667,3670],{},[76,3660,3661],{},[34,3662,3663],{},"Full Estate Assessment",[76,3665,3666],{},"The whole estate",[76,3668,3669],{},"2–4 weeks",[76,3671,3672],{},"Complete inventory, risk report and remediation plan",[55,3674,3675,3682,3685,3688],{},[76,3676,3677],{},[34,3678,3679],{},[198,3680,3681],{"href":1902},"Continuous Drift Monitoring",[76,3683,3684],{},"Ongoing",[76,3686,3687],{},"Subscription",[76,3689,3690],{},"Keep the inventory, risk and license picture current",[19,3692,3694],{"id":3693},"what-you-walk-away-with","What you walk away with",[12,3696,3697,3698,3700,3701,3703,3704,37],{},"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 ",[198,3699,2236],{"href":2235},", which need ",[198,3702,2626],{"href":2625},", and which Oracle installs to ",[198,3705,3706],{"href":409},"migrate or keep",{"title":413,"searchDepth":414,"depth":415,"links":3708},[3709,3710,3711,3712,3713],{"id":3514,"depth":414,"text":3515},{"id":3528,"depth":414,"text":3529},{"id":3576,"depth":414,"text":3577},{"id":3620,"depth":414,"text":3621},{"id":3693,"depth":414,"text":3694},"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.","Start here","i-lucide-radar",{},[3720,3721,3722,3723,3724],"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",{"title":3509,"description":3714},"services\u002Fjvm-discovery","xwCt4w5iuENInyc5KpzKLmV4sk8GzNe5e1H4Q9b7mV8",{"id":3729,"title":3730,"body":3731,"category":428,"description":3831,"engagement":3832,"extension":432,"headline":3833,"icon":3834,"meta":3835,"navigation":433,"order":414,"outcomes":3836,"path":409,"seo":3842,"stem":3843,"__hash__":3844},"services\u002Fservices\u002Fopenjdk-migration.md","Oracle Java Licensing & OpenJDK Migration",{"type":9,"value":3732,"toc":3821},[3733,3737,3743,3749,3756,3761,3765,3769,3776,3780,3783,3787,3790,3794,3800,3804],[19,3734,3736],{"id":3735},"why-this-is-urgent","Why this is urgent",[12,3738,3739,3740,3742],{},"Since January 2023, Oracle has sold Java SE through the ",[34,3741,460],{},", 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.",[12,3744,3745,3746,37],{},"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 ",[34,3747,3748],{},"$630,000 a year",[12,3750,3751,3752,3755],{},"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 ",[198,3753,3754],{"href":436},"closed on September 16, 2026",". Continuing to patch it now requires a paid subscription.",[177,3757,3758],{},[12,3759,3760],{},"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.",[19,3762,3764],{"id":3763},"what-we-do","What we do",[187,3766,3768],{"id":3767},"_1-quantify-the-exposure","1. Quantify the exposure",[12,3770,3771,3772,3775],{},"Using the ",[198,3773,3774],{"href":404},"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.",[187,3777,3779],{"id":3778},"_2-decide-install-by-install","2. Decide, install by install",[12,3781,3782],{},"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.",[187,3784,3786],{"id":3785},"_3-migrate","3. Migrate",[12,3788,3789],{},"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.",[187,3791,3793],{"id":3792},"_4-prove-it","4. Prove it",[12,3795,3796,3797,3799],{},"Uninstalling is not the same as re-pointing ",[1029,3798,1079],{},". We verify that Oracle binaries are actually gone and keep the evidence, which you will want if Oracle ever asks.",[19,3801,3803],{"id":3802},"further-reading","Further reading",[27,3805,3806,3811,3816],{},[30,3807,3808],{},[198,3809,3810],{"href":436},"Oracle JDK 21's free update window has closed",[30,3812,3813],{},[198,3814,3815],{"href":200},"Oracle's employee-based Java pricing, explained",[30,3817,3818],{},[198,3819,3820],{"href":247},"An Oracle JDK to OpenJDK migration checklist",{"title":413,"searchDepth":414,"depth":415,"links":3822},[3823,3824,3830],{"id":3735,"depth":414,"text":3736},{"id":3763,"depth":414,"text":3764,"children":3825},[3826,3827,3828,3829],{"id":3767,"depth":415,"text":3768},{"id":3778,"depth":415,"text":3779},{"id":3785,"depth":415,"text":3786},{"id":3792,"depth":415,"text":3793},{"id":3802,"depth":414,"text":3803},"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",{},[3837,3838,3839,3840,3841],"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":3730,"description":3831},"services\u002Fopenjdk-migration","0aWf4Vd_7P0phaKwOWxq3bLjO4iX8gdRjDu_tPGAWBY",{"id":3846,"title":2236,"body":3847,"category":2675,"description":3944,"engagement":3945,"extension":432,"headline":3946,"icon":3947,"meta":3948,"navigation":433,"order":415,"outcomes":3949,"path":2235,"seo":3954,"stem":3955,"__hash__":3956},"services\u002Fservices\u002Frapid-patch.md",{"type":9,"value":3848,"toc":3938},[3849,3853,3856,3863,3867,3874,3886,3890,3924,3929,3932],[19,3850,3852],{"id":3851},"the-premise","The premise",[12,3854,3855],{},"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.",[12,3857,3858,3859,3862],{},"Rapid Patch ",[34,3860,3861],{},"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.",[19,3864,3866],{"id":3865},"who-its-for","Who it's for",[12,3868,3869,3870,3873],{},"Applications that score below the critical threshold in our ",[198,3871,3872],{"href":3572},"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.",[12,3875,3876,3877,3880,3881,3885],{},"Rapid Patch covers ",[34,3878,3879],{},"same-major security patches"," (for example 17.0.x to the next 17.0.x). Major version upgrades and vendor swaps are ",[198,3882,3884],{"href":3883},"\u002Fapproach#patch-types","different engagements"," with a different risk profile.",[19,3887,3889],{"id":3888},"how-it-works","How it works",[27,3891,3892,3897,3903,3909,3914],{},[30,3893,3894,3896],{},[34,3895,2312],{},": canary at 1%, then 10%, then 100%, gated on automated health checks",[30,3898,3899,3902],{},[34,3900,3901],{},"Observability as the safety net",": error rates, latency, GC pause times, heap and thread behavior compared before and after the patch",[30,3904,3905,3908],{},[34,3906,3907],{},"Fast, rehearsed rollback",": the previous runtime stays in place until the soak period ends, and rollback is exercised, not just written down",[30,3910,3911,3913],{},[34,3912,2491],{}," for the paths that matter, in place of a full regression suite",[30,3915,3916,3919,3920,3923],{},[34,3917,3918],{},"A pre-flight check"," for ",[198,3921,3922],{"href":1164},"known failure modes",": APM agents, TLS defaults, GC flags",[1887,3925,3926],{},[12,3927,3928],{},"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.",[19,3930,3931],{"id":2264},"Governance",[12,3933,3934,3935],{},"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. ",[198,3936,3937],{"href":2256},"How we get this past a CAB →",{"title":413,"searchDepth":414,"depth":415,"links":3939},[3940,3941,3942,3943],{"id":3851,"depth":414,"text":3852},{"id":3865,"depth":414,"text":3866},{"id":3888,"depth":414,"text":3889},{"id":2264,"depth":414,"text":3931},"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",{},[3950,3951,3952,3953],"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":2236,"description":3944},"services\u002Frapid-patch","qDIP1lgG0nnDOEyokq47L3LSfKbmYPHSlBnCXM3udLw",{"id":3958,"title":2626,"body":3959,"category":2252,"description":4043,"engagement":4044,"extension":432,"headline":4045,"icon":4046,"meta":4047,"navigation":433,"order":1578,"outcomes":4048,"path":2625,"seo":4053,"stem":4054,"__hash__":4055},"services\u002Fservices\u002Fcritical-patch-assurance.md",{"type":9,"value":3960,"toc":4031},[3961,3965,3972,3978,3982,3986,3989,3993,3996,4000,4003,4007,4010,4014,4017,4021,4024,4028],[19,3962,3964],{"id":3963},"a-different-promise","A different promise",[12,3966,3967,3968,3971],{},"For business-critical applications the value proposition flips. We aren't removing testing. We ",[34,3969,3970],{},"compress"," it so that each test cycle is shorter and gives you more confidence, and full rigor becomes possible on a faster cadence.",[12,3973,3974,3975,3977],{},"This is a different engagement from ",[198,3976,2236],{"href":2235},", built on a different premise, not the same thing done more carefully.",[19,3979,3981],{"id":3980},"whats-in-it","What's in it",[187,3983,3985],{"id":3984},"test-impact-analysis-and-risk-based-test-selection","Test impact analysis and risk-based test selection",[12,3987,3988],{},"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.",[187,3990,3992],{"id":3991},"shadow-traffic-and-dark-launch-testing","Shadow traffic and dark launch testing",[12,3994,3995],{},"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.",[187,3997,3999],{"id":3998},"upgrade-readiness-assessment","Upgrade readiness assessment",[12,4001,4002],{},"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.",[187,4004,4006],{"id":4005},"staging-and-production-parity-audits","Staging and production parity audits",[12,4008,4009],{},"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.",[187,4011,4013],{"id":4012},"canary-gates-on-business-metrics","Canary gates on business metrics",[12,4015,4016],{},"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.",[187,4018,4020],{"id":4019},"patch-trains-and-war-room-support","Patch trains and war-room support",[12,4022,4023],{},"Scheduled, batched patch windows for critical apps, with dedicated live support during rollout, instead of ad hoc patching.",[187,4025,4027],{"id":4026},"lts-aligned-strategy-and-vendor-coordination","LTS-aligned strategy and vendor coordination",[12,4029,4030],{},"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":413,"searchDepth":414,"depth":415,"links":4032},[4033,4034],{"id":3963,"depth":414,"text":3964},{"id":3980,"depth":414,"text":3981,"children":4035},[4036,4037,4038,4039,4040,4041,4042],{"id":3984,"depth":415,"text":3985},{"id":3991,"depth":415,"text":3992},{"id":3998,"depth":415,"text":3999},{"id":4005,"depth":415,"text":4006},{"id":4012,"depth":415,"text":4013},{"id":4019,"depth":415,"text":4020},{"id":4026,"depth":415,"text":4027},"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",{},[4049,4050,4051,4052],"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":2626,"description":4043},"services\u002Fcritical-patch-assurance","utoXA8F7946svO9yfDqjkPV5VtPJhDVhuelRoxSfZeU",{"id":4057,"title":4058,"body":4059,"category":3495,"description":4127,"engagement":4128,"extension":432,"headline":4129,"icon":4130,"meta":4131,"navigation":433,"order":802,"outcomes":4132,"path":3474,"seo":4138,"stem":4139,"__hash__":4140},"services\u002Fservices\u002Fthird-party-applications.md","Vendor & Third-Party Application JVMs",{"type":9,"value":4060,"toc":4123},[4061,4065,4074,4077,4079,4118],[19,4062,4064],{"id":4063},"the-jvms-nobody-owns","The JVMs nobody owns",[12,4066,4067,4068,4071,4072,37],{},"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 ",[34,4069,4070],{},"own private JVM",", installed outside the package manager and invisible to anything that only checks the system ",[1029,4073,1099],{},[12,4075,4076],{},"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.",[19,4078,3764],{"id":3763},[27,4080,4081,4090,4096,4106,4112],{},[30,4082,4083,2970,4086,4089],{},[34,4084,4085],{},"Find and attribute them.",[198,4087,4088],{"href":404},"Discovery"," surfaces bundled runtimes and ties each one to a product, version and business owner.",[30,4091,4092,4095],{},[34,4093,4094],{},"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?",[30,4097,4098,4101,4102,4105],{},[34,4099,4100],{},"Patch what can be patched."," Through vendor updates or supported runtime swaps, rolled out with the same ",[198,4103,4104],{"href":2235},"detection and rollback discipline"," as your own apps.",[30,4107,4108,4111],{},[34,4109,4110],{},"Protect what can't."," Network isolation, disabling vulnerable features, tighter access. The compensating controls are documented so your risk register reflects reality.",[30,4113,4114,4117],{},[34,4115,4116],{},"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.",[390,4119,4120],{},[12,4121,4122],{},"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":413,"searchDepth":414,"depth":415,"links":4124},[4125,4126],{"id":4063,"depth":414,"text":4064},{"id":3763,"depth":414,"text":3764},"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",{},[4133,4134,4135,4136],"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":4137},"certified JDKs, SBOMs, patch timelines",{"title":4058,"description":4127},"services\u002Fthird-party-applications","oy1ThKLwcn-G3Z5DaUWp8Maj1EXsbbInm5duRfzyfRs",{"id":4142,"title":3681,"body":4143,"category":1933,"description":4211,"engagement":4212,"extension":432,"headline":3687,"icon":4213,"meta":4214,"navigation":433,"order":437,"outcomes":4215,"path":1902,"seo":4220,"stem":4221,"__hash__":4222},"services\u002Fservices\u002Fdrift-monitoring.md",{"type":9,"value":4144,"toc":4206},[4145,4149,4152,4155,4159,4195,4199],[19,4146,4148],{"id":4147},"assessments-go-stale","Assessments go stale",[12,4150,4151],{},"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.",[12,4153,4154],{},"Continuous Drift Monitoring keeps the picture current. The inventory becomes a system of record instead of a PDF.",[19,4156,4158],{"id":4157},"what-it-watches","What it watches",[27,4160,4161,4167,4173,4179,4185],{},[30,4162,4163,4166],{},[34,4164,4165],{},"New and undocumented JVMs"," across hosts, containers and artifact repositories",[30,4168,4169,4172],{},[34,4170,4171],{},"Patch-level drift",": which runtimes fell behind after each quarterly critical patch update",[30,4174,4175,4178],{},[34,4176,4177],{},"New CVEs"," against the versions and dependencies you actually run",[30,4180,4181,4184],{},[34,4182,4183],{},"License exposure changes",": a new Oracle JDK install is flagged before it shows up in an audit",[30,4186,4187,4190,4191,4194],{},[34,4188,4189],{},"Classification triggers",", such as a new regulated data flow, a traffic spike or an incident, which force an application's ",[198,4192,4193],{"href":3572},"risk tier"," to be re-scored",[19,4196,4198],{"id":4197},"how-its-delivered","How it's delivered",[12,4200,4201,4202,4205],{},"Collection reuses the minimum-privilege methods from the ",[198,4203,4204],{"href":404},"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":413,"searchDepth":414,"depth":415,"links":4207},[4208,4209,4210],{"id":4147,"depth":414,"text":4148},{"id":4157,"depth":414,"text":4158},{"id":4197,"depth":414,"text":4198},"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",{},[4216,4217,4218,4219],"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":3681,"description":4211},"services\u002Fdrift-monitoring","Phmhi-GcB9IZ5dN4HFjsW_dg9QF_D9rXUNzILnRNAKE",1790355849789]