網(wǎng)環(huán)境從解壓到驗(yàn)證)
簡介本資源為 Java 14 的 OpenJDK JRE 運(yùn)行環(huán)境安裝包面向需要在 Windows 平臺運(yùn)行 Java 14 應(yīng)用的開發(fā)者與運(yùn)維人員尤其適合 Red Hat 系環(huán)境下的部署與測試場景。壓縮包共 358 個文件約 59.57MB以 82 個 dll 動態(tài)鏈接庫、25 個 exe 可執(zhí)行程序及大量 license、assembly_exception 許可與異常說明文件為主另含 policy 安全策略、properties 配置、cacerts 證書庫、modules 模塊定義與 release 版本信息等構(gòu)成完整的 JRE 運(yùn)行時目錄結(jié)構(gòu)。已有 622 人學(xué)習(xí)下載可作為搭建 Java 14 運(yùn)行環(huán)境的直接來源省去自行編譯或跨平臺適配的麻煩。包內(nèi)保留完整的許可與異常說明便于合規(guī)審查cacerts 與 policy 文件可直接用于安全通信與權(quán)限控制modules 與 release 信息則方便確認(rèn)版本與模塊化配置適合快速部署、版本核對及運(yùn)行環(huán)境排錯參考。1. 別被文件名騙了java-14-openjdk-jre-14.0.1.7-1.windows.redhat.x86_64.zip 到底是什么java-14-openjdk-jre-14.0.1.7-1.windows.redhat.x86_64.zip這個文件名第一眼看過去像是一堆版本號堆出來的亂碼但它其實(shí)是一條完整的“身份信息鏈”。拆開看java-14是大版本openjdk是上游實(shí)現(xiàn)jre說明它只含運(yùn)行時不含編譯器14.0.1.7-1是發(fā)行方自己的補(bǔ)丁號windows是目標(biāo)系統(tǒng)redhat是打包方x86_64是架構(gòu)。很多人第一次拿到它是在一臺不能聯(lián)網(wǎng)的內(nèi)網(wǎng) Windows 機(jī)器上需要跑一個只認(rèn) Java 14 的老服務(wù)而機(jī)器上既沒有包管理器也沒有外網(wǎng)。這時候這個 zip 就是唯一的救命稻草。它解決的不是“學(xué) Java”的問題而是“在一臺干凈、隔離、架構(gòu)確定的 Windows 機(jī)器上把 Java 14 運(yùn)行時精確地鋪進(jìn)去”的問題。適合誰適合做離線部署、內(nèi)網(wǎng)運(yùn)維、老系統(tǒng)維護(hù)以及需要固定 JDK 版本做構(gòu)建驗(yàn)證的工程師。如果你只是本地寫代碼裝個新版 JDK 更省事但如果你面對的是“版本必須鎖死、網(wǎng)絡(luò)必須隔離、架構(gòu)必須匹配”的場景這個文件名的每一個字段都不能錯。2. 拆解文件名每個字段決定了你能不能跑起來2.1 為什么是 JRE 而不是 JDKjre這三個字母決定了這個包能做什么、不能做什么。JRE 只包含 Java 虛擬機(jī)、核心類庫和運(yùn)行時需要的配置文件不包含javac、jar、jdb這些開發(fā)工具。如果你的目標(biāo)機(jī)器只是運(yùn)行一個已經(jīng)打好的.jar或.warJRE 足夠而且體積更小、攻擊面更窄。但如果你需要在目標(biāo)機(jī)器上編譯代碼、執(zhí)行jarsigner或者用jcmd做診斷JRE 會讓你在第一步就卡住。常見做法是部署環(huán)境用 JRE構(gòu)建環(huán)境用 JDK。我一般會在內(nèi)網(wǎng)維護(hù)兩份包一份 JRE 用于生產(chǎn)節(jié)點(diǎn)一份 JDK 用于跳板機(jī)上的構(gòu)建。判斷標(biāo)準(zhǔn)很簡單——目標(biāo)機(jī)器上有沒有javac的需求。沒有就堅決用 JRE少一個工具就少一個被掃描到的入口。2.2 版本號 14.0.1.7-1 里的發(fā)行方邏輯14.0.1是 OpenJDK 的官方版本7-1是 Red Hat 自己的構(gòu)建號和發(fā)行號。這里最容易翻車的地方是很多人以為14.0.1就是全部忽略了后面的7-1。不同發(fā)行方對同一個上游版本會打不同的補(bǔ)丁尤其是安全修復(fù)和 Windows 平臺相關(guān)的兼容性修復(fù)。7通常表示 Red Hat 的第 7 次構(gòu)建-1是發(fā)行修訂號。這意味著如果你在 A 機(jī)器上用官方 OpenJDK 14.0.1 驗(yàn)證通過換到 B 機(jī)器上用這個 Red Hat 構(gòu)建理論上 API 行為一致但底層庫鏈接、證書庫路徑、甚至默認(rèn)字符集都可能不同。我遇到過最隱蔽的一次是java.security文件里默認(rèn)禁用的算法列表不一樣導(dǎo)致一個老 TLS 握手在官方包上能過、在發(fā)行版包上直接拒絕。所以版本號必須完整記錄不能只寫14.0.1。2.3 windows.redhat.x86_64 三個字段的硬約束windows說明這是 Windows 平臺專用里面的可執(zhí)行文件是.exe和.dll不是 Linux 的.so。x86_64說明它是 64 位能在 64 位 Windows 上跑但不能在 32 位系統(tǒng)上跑也不能在 ARM 架構(gòu)的 Windows 上直接跑。redhat說明打包方是 Red Hat這通常意味著它來自 Red Hat 的構(gòu)建流水線可能帶有 Red Hat 自己的元數(shù)據(jù)和目錄結(jié)構(gòu)。這三個字段是硬約束錯一個就完全不能用。我見過有人把x86_64的包解壓到 32 位 Windows 上然后困惑為什么java.exe雙擊沒反應(yīng)——其實(shí)是 PE 頭架構(gòu)不匹配系統(tǒng)直接拒絕加載。也見過把 Windows 包解壓到 Linux 上然后試圖執(zhí)行java.exe結(jié)果當(dāng)然是Exec format error。文件名就是契約不要試圖繞過。2.4 zip 格式在離線部署中的實(shí)際意義為什么是zip而不是msi或exe安裝包因?yàn)?zip 是“綠色”的解壓即用不寫注冊表不往Program Files里塞東西不需要管理員權(quán)限。這在離線、隔離、多版本共存的環(huán)境里是巨大優(yōu)勢。你可以把不同版本的 JRE 解壓到不同目錄用絕對路徑調(diào)用互不干擾。但 zip 也意味著沒有自動配置。JAVA_HOME要自己設(shè)PATH要自己加文件關(guān)聯(lián)要自己建。很多人解壓完發(fā)現(xiàn)java -version還是系統(tǒng)里舊版本就是因?yàn)镻ATH里舊路徑排在前面。zip 包給你的是完全控制權(quán)代價是你要自己承擔(dān)配置責(zé)任。3. 在 Windows 上把 JRE 14 鋪進(jìn)內(nèi)網(wǎng)機(jī)器從解壓到驗(yàn)證3.1 解壓位置的選擇與目錄結(jié)構(gòu)確認(rèn)不要解壓到C:\Program Files下面除非你有管理員權(quán)限并且確定不會有多版本沖突。我一般會選C:\java\作為根下面按版本建目錄比如C:\java\jre-14.0.1.7。這樣路徑短、無空格、權(quán)限簡單后續(xù)腳本引用也方便。解壓后先看目錄結(jié)構(gòu)。典型的 JRE 包解壓出來應(yīng)該有一個bin目錄里面有java.exe、javaw.exe、keytool.exe等一個lib目錄里面有modules、rt.jarJava 14 其實(shí)已經(jīng)模塊化了但發(fā)行版可能保留一些兼容文件一個conf目錄里面有security和net.properties。如果解壓出來只有一層空目錄或者文件散落說明解壓工具沒有保留目錄結(jié)構(gòu)需要換工具重新解壓。# 在 Windows 上可以用 PowerShell 解壓保留目錄結(jié)構(gòu) Expand-Archive -Path java-14-openjdk-jre-14.0.1.7-1.windows.redhat.x86_64.zip -DestinationPath C:\java\jre-14.0.1.7Expand-Archive是 PowerShell 內(nèi)置命令不需要額外安裝。-DestinationPath指定的目錄如果不存在會自動創(chuàng)建。注意如果 zip 包里有很長的路徑或者特殊字符老版本 PowerShell 可能報錯這時候用 7-Zip 的命令行版本更穩(wěn)。3.2 設(shè)置 JAVA_HOME 和 PATH 的正確順序解壓完只是第一步環(huán)境變量才是讓系統(tǒng)找到它的關(guān)鍵。JAVA_HOME指向 JRE 根目錄PATH里加上%JAVA_HOME%\bin。順序很重要如果系統(tǒng)里已經(jīng)有其他 Java必須把新路徑放在最前面否則java -version會顯示舊版本。# 以管理員身份運(yùn)行 PowerShell設(shè)置系統(tǒng)級環(huán)境變量 [Environment]::SetEnvironmentVariable(JAVA_HOME, C:\java\jre-14.0.1.7, Machine) $oldPath [Environment]::GetEnvironmentVariable(PATH, Machine) $newPath C:\java\jre-14.0.1.7\bin; $oldPath [Environment]::SetEnvironmentVariable(PATH, $newPath, Machine)這里用Machine級別而不是User級別是因?yàn)閮?nèi)網(wǎng)服務(wù)經(jīng)常以系統(tǒng)賬戶運(yùn)行用戶級變量對它不可見。$oldPath先讀出來再拼接避免覆蓋掉原有 PATH。改完之后必須新開一個終端窗口舊窗口的環(huán)境變量是啟動時快照不會自動刷新。3.3 驗(yàn)證安裝java -version 之外的三個檢查java -version只能告訴你版本號不能告訴你這個 JRE 是否完整、證書庫是否可用、模塊是否齊全。我一般會做三個額外檢查。第一個檢查java -XshowSettings:properties -version它會打印出java.home、java.version、os.arch等關(guān)鍵屬性。確認(rèn)java.home指向你解壓的目錄os.arch是amd64。第二個檢查keytool -list -cacerts確認(rèn)證書庫能打開。如果這一步報錯說明conf\security\cacerts文件缺失或損壞后續(xù)任何 HTTPS 請求都會失敗。第三個檢查用一個最小 Java 程序驗(yàn)證運(yùn)行時。寫一個Hello.java用另一臺機(jī)器上的 JDK 編譯成 class然后拷到目標(biāo)機(jī)器上用這個 JRE 運(yùn)行。這一步能驗(yàn)證類加載、字節(jié)碼版本兼容性。# 在目標(biāo)機(jī)器上運(yùn)行已編譯的 class C:\java\jre-14.0.1.7\bin\java -cp . Hello # 輸出 Hello, Java 14 說明運(yùn)行時正常如果java -version正常但運(yùn)行 class 報UnsupportedClassVersionError說明編譯用的 JDK 版本高于 14需要降級編譯或者換 JDK。3.4 用腳本批量部署到多臺機(jī)器內(nèi)網(wǎng)機(jī)器往往不止一臺手動解壓設(shè)變量效率太低。我一般會寫一個批處理腳本放在共享目錄里每臺機(jī)器執(zhí)行一次。echo off setlocal set SRC\\fileserver\share\java-14-openjdk-jre-14.0.1.7-1.windows.redhat.x86_64.zip set DSTC:\java\jre-14.0.1.7 if exist %DST% ( echo Already exists, skipping extract. ) else ( mkdir %DST% powershell -Command Expand-Archive -Path %SRC% -DestinationPath %DST% -Force ) setx JAVA_HOME %DST% /M setx PATH %DST%\bin;%PATH% /M echo Done. Open a new terminal to verify. endlocalsetx是 Windows 自帶的設(shè)置環(huán)境變量命令/M表示系統(tǒng)級。注意setx有長度限制如果 PATH 已經(jīng)很長可能會截斷所以更穩(wěn)的做法還是用 PowerShell 的SetEnvironmentVariable。腳本里先判斷目錄是否存在避免重復(fù)解壓覆蓋配置。4. 避坑指南JRE 14 離線部署里最容易翻車的五件事4.1 解壓后 java.exe 雙擊閃退現(xiàn)象解壓完進(jìn)bin目錄雙擊java.exe窗口一閃而過什么都沒看到。原因java.exe是控制臺程序雙擊時如果沒有參數(shù)它會打印用法然后立即退出。這不是故障是正常行為。真正的故障是雙擊后連窗口都不出現(xiàn)那可能是 PE 架構(gòu)不匹配或者依賴的 DLL 缺失。解決不要雙擊用cmd打開命令行cd到bin目錄執(zhí)行java.exe -version。如果報“不是有效的 Win32 應(yīng)用程序”說明架構(gòu)錯了檢查是不是 32 位系統(tǒng)裝了 64 位包。如果報缺少msvcp140.dll說明需要裝 VC 運(yùn)行庫。4.2 PATH 改了但 java -version 還是舊版本現(xiàn)象環(huán)境變量里明明加了新路徑新開終端執(zhí)行java -version還是顯示 Java 8 或 11。原因PATH 里舊 Java 的路徑排在新路徑前面或者系統(tǒng)里存在C:\Windows\System32\java.exe這個“幽靈”文件。Windows 的搜索順序是當(dāng)前目錄 → PATH 從左到右System32 往往在 PATH 很靠前的位置。解決用where java命令列出所有匹配的java.exe看第一個是哪個。如果是 System32 下的直接刪掉或者重命名需要管理員權(quán)限。如果是舊版本路徑在前調(diào)整 PATH 順序把新路徑移到最前面。4.3 證書庫報錯導(dǎo)致 HTTPS 全部失敗現(xiàn)象Java 程序啟動時報PKIX path building failed或者unable to find valid certification path。原因JRE 自帶的cacerts文件不包含目標(biāo)服務(wù)用的根證書或者cacerts文件在解壓過程中損壞。內(nèi)網(wǎng)服務(wù)經(jīng)常用自簽名證書默認(rèn)證書庫當(dāng)然不認(rèn)。解決用keytool -importcert把內(nèi)網(wǎng)根證書導(dǎo)入cacerts。導(dǎo)入前先備份原文件。命令是keytool -importcert -alias internal-ca -file ca.crt -keystore cacerts -storepass changeit。默認(rèn)密碼是changeit如果發(fā)行版改過需要查發(fā)行方文檔。4.4 模塊化之后反射報 IllegalAccessError現(xiàn)象老代碼在 Java 8 上跑得好好的換到 Java 14 的 JRE 上啟動時報IllegalAccessError或者InaccessibleObjectException。原因Java 9 引入模塊系統(tǒng)后JDK 內(nèi)部 API 被封裝了。很多老框架用反射訪問sun.misc.Unsafe或者java.lang的內(nèi)部字段在 Java 14 上默認(rèn)被拒絕。解決臨時方案是加--add-opens參數(shù)比如--add-opens java.base/java.langALL-UNNAMED。但這不是長久之計每個需要開放的包都要加參數(shù)會越來越長。根本方案是升級框架版本或者聯(lián)系框架維護(hù)方適配新版本。我一般會先用--add-opens讓服務(wù)跑起來然后排期做框架升級。4.5 多版本共存時 JAVA_HOME 被覆蓋現(xiàn)象機(jī)器上同時有 Java 8 和 Java 14裝完 14 之后某個依賴 Java 8 的服務(wù)啟動失敗。原因JAVA_HOME是全局的改成 14 之后所有讀這個變量的服務(wù)都受影響。有些服務(wù)在啟動腳本里硬編碼了JAVA_HOME有些則依賴系統(tǒng)變量。解決不要改全局JAVA_HOME而是在每個服務(wù)的啟動腳本里顯式指定。比如set JAVA_HOMEC:\java\jre-8放在腳本開頭只對當(dāng)前進(jìn)程生效。這樣多版本可以和平共處互不干擾。全局變量只保留一個“默認(rèn)”版本給交互式命令行用。5. 進(jìn)階技巧把 JRE 14 做成可復(fù)用的內(nèi)網(wǎng)基線5.1 用 jlink 裁剪出更小的運(yùn)行時JRE 14 完整包解壓后大概 200MB 左右如果目標(biāo)機(jī)器磁盤緊張或者要分發(fā)給很多節(jié)點(diǎn)可以用jlink裁剪。jlink在 JDK 里不在 JRE 里所以需要在一臺有 JDK 14 的機(jī)器上操作。# 在 JDK 14 環(huán)境下裁剪一個只含 java.base 和 java.logging 的運(yùn)行時 jlink --module-path C:\java\jdk-14\jmods --add-modules java.base,java.logging --output C:\java\jre-min-14 --strip-debug --compress2 --no-header-files --no-man-pages--add-modules指定保留的模塊只保留程序真正用到的。--strip-debug去掉調(diào)試信息--compress2啟用壓縮--no-header-files和--no-man-pages去掉 C 頭文件和手冊頁。裁剪完可能只有 40-50MB。但要注意如果程序用了未列出的模塊運(yùn)行時會報ModuleNotFoundException所以裁剪前要用jdeps分析依賴。5.2 用 jdeps 分析程序真正依賴哪些模塊jdeps也是 JDK 工具能掃描 class 文件或 jar 包列出它依賴的模塊和包。# 分析一個 jar 包的模塊依賴 jdeps --multi-release 14 --print-module-deps --ignore-missing-deps myapp.jar # 輸出類似java.base,java.logging,java.sql--print-module-deps直接輸出模塊列表可以喂給jlink的--add-modules。--ignore-missing-deps忽略找不到的依賴避免因?yàn)槿鄙倏蛇x依賴而中斷分析。這一步是裁剪的前提不分析就裁剪大概率會漏模塊。5.3 把配置固化成腳本模板內(nèi)網(wǎng)部署最怕“每臺機(jī)器手工配一遍”。我習(xí)慣把解壓、設(shè)變量、驗(yàn)證三步寫成一個模板腳本放在共享目錄新機(jī)器執(zhí)行一次就完成基線配置。腳本里用變量控制版本號和路徑換版本時只改變量。echo off setlocal set JRE_VERSION14.0.1.7 set JRE_ROOTC:\java\jre-%JRE_VERSION% set ZIP_NAMEjava-14-openjdk-jre-%JRE_VERSION%-1.windows.redhat.x86_64.zip set SHARE\\fileserver\share if not exist %JRE_ROOT% ( mkdir %JRE_ROOT% powershell -Command Expand-Archive -Path %SHARE%\%ZIP_NAME% -DestinationPath %JRE_ROOT% -Force ) powershell -Command [Environment]::SetEnvironmentVariable(JAVA_HOME, %JRE_ROOT%, Machine) powershell -Command $p[Environment]::GetEnvironmentVariable(PATH,Machine); if($p -notlike *%JRE_ROOT%\bin*){[Environment]::SetEnvironmentVariable(PATH,%JRE_ROOT%\bin;$p,Machine)} %JRE_ROOT%\bin\java.exe -version endlocal這個腳本的關(guān)鍵點(diǎn)是冪等重復(fù)執(zhí)行不會重復(fù)解壓也不會重復(fù)往 PATH 里塞路徑。if not exist判斷目錄-notlike判斷 PATH 里是否已包含。這樣即使誤操作跑了兩次也不會把 PATH 撐爆。5.4 驗(yàn)證基線是否生效的檢查清單部署完不是跑一下java -version就完事。我一般會做一個檢查清單每項(xiàng)都過了才算基線可用。檢查項(xiàng)命令預(yù)期結(jié)果版本正確java -version輸出包含 14.0.1.7架構(gòu)正確java -XshowSettings:properties -versionos.arch amd64證書庫可用keytool -list -cacerts -storepass changeit列出證書條目無報錯類加載正常運(yùn)行一個已編譯的 Hello.class輸出預(yù)期文本模塊完整java --list-modules包含程序需要的模塊環(huán)境變量echo %JAVA_HOME%指向解壓目錄這張表可以貼在部署文檔里每臺機(jī)器部署完逐項(xiàng)打勾??雌饋矸爆嵉确?wù)上線后半夜被叫起來排查要劃算得多。5.5 一個我踩過的坑別在 PATH 里留尾部反斜杠最后說一個血淚教訓(xùn)。有一次我在腳本里寫set PATH%JRE_ROOT%\bin\;%PATH%注意bin后面多了一個反斜杠。大部分時候沒問題但某些老程序的啟動腳本會拼接路徑多一個反斜杠導(dǎo)致C:\java\jre-14.0.1.7\bin\\java.exe這種雙反斜杠路徑Windows 有時能解析有時直接報“系統(tǒng)找不到指定的路徑”。排查了半天才發(fā)現(xiàn)是尾部反斜杠。從那以后我所有 PATH 拼接都嚴(yán)格檢查結(jié)尾不加多余分隔符。這個坑很小但很耗時間希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取