简介:JDK11 Windows 64位压缩免安装包面向需要在Windows环境下快速搭建Java开发或运行环境的开发者,尤其适合个人学习、多版本JDK并存以及缺少系统安装权限的场景。压缩包共423个文件,约171.44MB,包含dll动态库、jmod模块、exe可执行程序,以及license、copyright、md说明文档等,覆盖JDK运行时、开发工具和模块化依赖的主体内容,解压后即可按目录结构使用。该版本对应JDK11,涉及模块化系统、HTTP Client API、G1与ZGC垃圾收集器、JShell交互工具及String增强方法等知识点,便于读者直接对照学习Java 11的核心能力。目前已有1831人学习下载,可作为快速部署、版本验证和日常开发环境搭建的轻量选择。
1. 一个解压就能用的 JDK11:为什么我把它当构建机的标准件
去年接手一台内网构建机,第一件事是装 JDK,偏偏那台机器没有管理员权限,跑安装包要写注册表、要重启,重启完还有一半概率把机器上原有的 JDK 8 顶掉,第二天运维打电话来问谁动了环境。后来我就固定用 JDK11 window64 免安装压缩版:一个 zip 包,解压到任意有写权限的目录,落两个环境变量就能编译,不想要了整目录删掉,系统里不留任何痕迹。这类 JAVA JDK11 WINDOW64 免安装包最适合三类场景——同一台机器上 JDK 8 和 JDK 11 要并存的老项目维护者、没有管理员权限的受限机器、以及需要按项目锁版本、随时回滚的构建节点。下面按我自己的落地顺序走一遍:包解开后先看什么、环境变量怎么落、哪些地方最容易翻车、以及怎么把它裁成能塞进镜像的小运行时。
2. 解开之后先别配变量:目录职责、路径约束和一次离线自检
2.1 免安装版省掉的到底是什么
安装包做的事远不止复制文件:它写注册表键、往系统目录丢 java.exe、登记卸载项、改系统环境变量,有的还会顺手把已有的 java.exe 替换掉。免安装 zip 这些一件都不做,好处是删目录即卸载、多版本互不干扰、受限机器不需要提权;代价同样明显——没有任何工具会「自动发现」它。凡是靠注册表找 JDK 的安装程序、老版本 IDE、某些打包工具,都会绕开你解压的这份,跑的还是机器上原来那个 JDK。我一般把这个特性理解成「显式绑定」:任何要编译的东西,你都得明确告诉它 JDK 在哪,而不是指望它自己猜。
理解了这一点,后面的所有操作就有了解释:环境变量不是形式主义,它就是免安装版唯一的「注册表」。这也是为什么很多人解压完直接敲java -version发现是 1.8,然后怀疑包是坏的——包没问题,是系统根本没看见它。
2.2 目录里每个文件夹负责什么
解压后第一眼看到 bin、conf、include、jmods、legal、lib 六个目录,别急着只加 Path。后面 jlink 裁剪、JNI 编译、加密策略调整,都要回到这张表里找东西。
| 目录 | 关键内容 | 什么时候会动它 |
|---|---|---|
| bin | java、javac、jar、jshell、jlink、jmod、jcmd、jstack、jmap、keytool | 只加进 Path,不手动改 |
| conf | net.properties、security\java.security、logging.properties | 调代理、改加密策略、调日志级别 |
| include | jni.h、jni_md.h、jawt.h | 写 native 扩展或编译 JNI 时才用 |
| jmods | 约七十个 .jmod 模块文件 | jlink 裁剪运行时的原料,删不得 |
| legal | 各模块的许可证文本 | 二次分发时保留 |
| lib | modules(核心类库镜像)、ct.sym、部分发行版带 src.zip | 只读,别手删 |
有两个点容易被忽略。一是lib\tools.jar在 JDK 9 之后就没了,凡是启动脚本里还写-cp %JAVA_HOME%\lib\tools.jar的老工具,到 11 上必然报找不到类,这不是你解压坏了。二是lib\ct.sym这个文件,它是编译期校验 API 归属的符号表,Maven 的release参数就靠它工作,后面第 5 章还会用到。
2.3 解压路径的三条硬约束
路径选错,后面所有灵异问题都能追溯到这儿。
第一条,路径里不要有中文和空格。老版本的 Tomcat 启动脚本、部分 Ant 构建文件、一些国产中间件的安装器,拼JAVA_HOME时不加引号,D:\Program Files\jdk11会被拆成两段,报的错还特别隐蔽,说「系统找不到指定路径」。
第二条,不要放在%TEMP%、同步盘目录、网络映射盘。同步盘会在后台锁文件,jlink 和 jmod 读写.jmod时直接失败;网络盘上的 JDK 启动会比本地慢一个数量级,编译大项目时体感很差。
第三条,不要放在C:\Program Files及其子目录。那下面默认需要提权才能写,某些工具会在 JDK 目录里生成临时文件或缓存,一写就权限拒绝。
我自己的习惯是统一放D:\runtime\jdk11,所有机器一个路径,切换脚本和 CI 配置可以直接复用,省掉一堆路径拼接的破事。
2.4 不配环境变量的第一次验证
这一步的价值在于把「包的问题」和「环境变量的问题」切开。不配任何变量,直接用绝对路径跑:
cd /d D:\runtime\jdk11 .\bin\java -version .\bin\javac -version .\bin\java --list-modules | findstr /i "java.se"三行的含义分别是:java -version确认运行时能启动,正常会打出类似11.x.x的版本行和三行内部版本信息;javac -version确认编译器在,免安装包偶尔会因为解压工具不完整丢文件,javac 是最容易被漏掉的一个;第三条列出模块并过滤java.se,能看到java.se@11.x.x说明模块镜像完整,jlink 后面才有得玩。
顺带做一次完整性校验,压缩包下载完先别解压:
certutil -hashfile jdk11_windows-x64_bin.zip SHA256把输出和下载页给的值对一遍。这一步不是洁癖,我遇到过压缩包在浏览器里下到 90% 就断了、解压工具却只报一个「文件已损坏」的情况,白排查半小时。解压工具用系统自带的资源管理器或者 7-Zip 都行,避免用那些会按本地编码改写文件名的老工具,legal目录里有非 ASCII 文件名,改完就可能解压报错。
3. 环境变量:JAVA_HOME 指向哪、Path 排第几、多版本怎么切
3.1 为什么 JAVA_HOME 必须指根目录
JAVA_HOME不是一个官方强制的变量,它是生态里约定俗成的约定:Maven、Gradle、Tomcat 的 startup 脚本、Ant、各种 shell 包装器,都会自己拼%JAVA_HOME%\bin\java。你把它指到bin目录,人家拼出来就是bin\bin\java,报错信息往往只是一句「找不到文件」,看不出根因。你把它指到jre子目录,Maven 会直接甩一句JAVA_HOME should point to a JDK not a JRE——顺带说一句,JDK 11 起上游不再单独发 JRE 了,这个报错在 11 上反而少见了,但从 JDK 8 时代带过来的「指到 jre」习惯还是会让一些人翻车。
判断标准很简单:%JAVA_HOME%\bin\javac.exe存在,指向就是对的。只有 java.exe 没有 javac.exe,说明指到运行时上了。
3.2 两种配置方式,以及一个必须避开的坑
图形界面那条路没什么好说的:系统属性 → 高级 → 环境变量 → 新建系统变量JAVA_HOME,再编辑Path。命令行走setx更快,但有个血泪经验必须提前说:
REM 正确:只写 JAVA_HOME setx JAVA_HOME "D:\runtime\jdk11" /M REM 危险:不要用 setx 覆盖 Path REM setx PATH "%JAVA_HOME%\bin;%PATH%" /M被注释掉的那行是很多人踩过的雷。setx对 PATH 有长度限制,系统 PATH 一旦超过一千字符就会被静默截断,截断之后系统里一堆工具找不到命令,重启前你甚至不知道发生了什么。改 PATH 一律走图形界面,或者用 PowerShell 的 .NET 方法,可控得多:
# 以管理员身份运行 [Environment]::SetEnvironmentVariable("JAVA_HOME", "D:\runtime\jdk11", "Machine") $old = [Environment]::GetEnvironmentVariable("Path", "Machine") if ($old -notlike "*D:\runtime\jdk11\bin*") { [Environment]::SetEnvironmentVariable("Path", "D:\runtime\jdk11\bin;$old", "Machine") }这里加了幂等判断,重复执行不会把同一条路径追加十遍。setx和SetEnvironmentVariable都只对新开的进程生效,当前已经开着的 cmd 窗口不会变,这一点每年都要坑一批人——改完变量发现没反应,先开个新窗口再说。
3.3 Path 顺序决定谁生效
Windows 按 Path 从左到右找可执行文件。如果C:\Windows\System32里躺着一个老安装器留下的 java.exe,而%JAVA_HOME%\bin排在它后面,你敲java跑的就是旧的。免安装版最怕这个,因为它的存在感完全依赖顺序。
排查只要一条命令:
where java where javac输出会有多行,第一行才是实际生效的那个。如果第一行是C:\Windows\System32\java.exe,两条路:把%JAVA_HOME%\bin挪到 Path 最前面,或者以管理员身份把 System32 下那几个 java 相关文件删掉(java.exe、javaw.exe、javaws.exe,删之前确认没有别的软件依赖)。我更倾向挪顺序,删系统目录文件属于不可逆操作,出问题不好回退。
3.4 多版本共存的切换脚本
免安装版最大的价值在这里。把 8、11、17 各解压一份到D:\runtime下面,写个批处理按需切换:
@echo off REM 用法: switch-jdk.bat 8 ^| 11 ^| 17 setlocal set "BASE=D:\runtime" if /i "%1"=="8" set "TARGET=%BASE%\jdk8" if /i "%1"=="11" set "TARGET=%BASE%\jdk11" if /i "%1"=="17" set "TARGET=%BASE%\jdk17" if not defined TARGET ( echo 未识别的版本号: %1 exit /b 1 ) if not exist "%TARGET%\bin\javac.exe" ( echo 目标目录不是完整 JDK: %TARGET% exit /b 1 ) setx JAVA_HOME "%TARGET%" echo 已切换到 %TARGET% echo 请重新打开命令行窗口后再验证 endlocal脚本里判断javac.exe而不是java.exe,是为了挡住「指到 JRE」这个经典错误。setx写的是用户级变量,不影响当前窗口,这是刻意保留的行为:切换 JDK 时最忌讳正在跑的构建进程读到一半变量变了,让它自然失效更安全。
配完之后再验证一遍,三个输出要对得上:
echo %JAVA_HOME% java -version javac -versionjava -version打出11.x,javac -version也必须打11.x。两者不一致,说明 Path 里有另一个 JDK 的 bin 排在前面,回到 3.3 用where找出来。
4. 避坑清单:五条 JDK11 免安装版的翻车记录
4.1 现象:命令行是 11,IDE 里还是 8
原因基本有两层。一层是 Path 顺序,命令行读的是你新加的 bin,IDE 读的是它自己记住的 JDK 路径;另一层是 IDE 的「内置 JDK」或者上一次项目配置里写死的 SDK。解决方式是两边分开查:命令行用where java确认生效文件,IDE 里到项目结构设置里单独把 SDK 指到D:\runtime\jdk11,再确认模块的 language level 和它一致。别指望配了系统变量 IDE 就自动跟。
4.2 现象:Maven 报 No compiler is provided in this environment
原因几乎都是JAVA_HOME指错了层。指到bin会拼出bin\bin\javac,指到 jre 目录则压根没有编译器。解决:把JAVA_HOME改回根目录,然后确认%JAVA_HOME%\bin\javac.exe这个文件真实存在。还有一种少见情况:PATH 里存在一个只有运行时的旧目录先被命中,mvn -version输出里那行Java home:会直接暴露它,看那一行比猜快。
4.3 现象:升级到 11 后启动就报 InaccessibleObjectException
原因是模块化之后的强封装,反射访问 JDK 内部包被拒绝。麻烦之处在于 JDK 11 的默认策略是--illegal-access=permit,只打警告不报错,所以很多人在 11 上跑得好好的,一换发行版或者加了deny参数就集体爆炸。解决是给具体模块开洞:
java --add-opens java.base/java.lang=ALL-UNNAMED ^ --add-opens java.base/java.util=ALL-UNNAMED ^ -jar app.jar开洞要精确到包,别图省事一上来就想全开。先在日志里找Unable to make ... accessible那行,它会把包名和类名都给出来,照着加就行。
4.4 现象:路径带空格,脚本启动一半就退出
原因是老脚本拼路径不加引号。这类问题在免安装版上比安装版高发,因为安装版默认装在Program Files下,脚本作者早就被迫处理过引号;免安装版路径五花八门,反而容易撞上。解决:路径统一不带空格与中文,这是最省事的;实在改不了路径,就去改脚本,把%JAVA_HOME%\bin\java全改成"%JAVA_HOME%\bin\java"。
4.5 现象:jlink 报 module not found
原因通常有三个:一是拿 JRE 目录去做 jlink,而 JRE 里没有 jmods;二是解压时为了省空间把jmods目录删了;三是--module-path指错了层级,指到了jmods的上级而不是它本身。解决:确认%JAVA_HOME%\jmods下有几十个.jmod文件,--module-path直接指这个目录。还有一种情况是模块名写错,java.sql写成javax.sql这种手滑,报错信息里会给候选列表,看仔细点能省一轮试错。
5. 接进项目:IDE 三处对齐、Maven 的 release、反射开洞
5.1 IDE 里要同时改的不止一处
在集成开发环境里把 JDK 换到 11,只改 SDK 是不够的,至少三处要一起动。项目结构里的 Project SDK 指向D:\runtime\jdk11;Project language level 选 11;构建工具面板里的 Java Compiler 目标字节码版本也要是 11。三者不一致的典型症状是:代码里var能写,编译出来却在低版本运行时上炸UnsupportedClassVersionError。另外构建工具的导入器有独立的 JDK 设置,Maven 那一栏里还有个「JDK for importer」,依赖解析走的是它,这块没改会出现「SDK 是 11,但依赖解析还在用旧 JDK」的怪现象。
5.2 Maven 用 release 而不是 source/target
这是我认为最值得强调的一条。source和target只控制语法级别和字节码版本,不校验你用到的 API 是否属于目标版本;release会拿lib\ct.sym做符号校验,用了高版本才有的方法直接编译失败。
<properties> <maven.compiler.release>11</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties>release参数从 JDK 9 起可用,正好配合免安装的 11。三个属性一起写的原因是编码问题:免安装包本身不决定源文件编码,Windows 上默认 GBK,源码是 UTF-8 时中文注释会变乱码,sourceEncoding定死 UTF-8 能省掉很多莫名其妙的编译报错。
如果机器上 JDK 版本比较乱,还可以上 toolchains 插件,在%USERPROFILE%\.m2\toolchains.xml里显式声明多个 JDK 路径,让 Maven 按项目要求挑,不依赖JAVA_HOME:
<toolchain> <type>jdk</type> <provides> <version>11</version> <vendor>custom</vendor> </provides> <configuration> <jdkHome>D:\runtime\jdk11</jdkHome> </configuration> </toolchain>version和vendor要跟构建脚本里的要求对得上,对不上时 Maven 会说找不到匹配的 toolchain,这句报错比JAVA_HOME指错清楚得多。
5.3 Gradle 侧用 toolchain 声明
java { toolchain { languageVersion = JavaLanguageVersion.of(11) } }Gradle 会按声明去找本机的 JDK,找不到就直接失败而不是悄悄降级,这个行为比静默回退安全。免安装版的好处在这里体现得很直接:多解压几个版本到D:\runtime,toolchain 能自动扫描到,不用来回改系统变量。
5.4 运行时参数别硬编码在脚本里
--add-opens这类参数如果散落在十几个启动脚本里,改一次要命。我一般用环境变量兜底:
set JAVA_TOOL_OPTIONS=--add-opens=java.base/java.lang=ALL-UNNAMED好处是所有 JVM 启动都会自动带上,调试时特别省事;坏处是它是个黑匣子——半年后别人接手,代码里找不到任何开洞痕迹,却怎么都复现不了你的环境。所以我的做法是只在临时排查时用它,确认要长期保留的参数一律写回启动脚本或容器配置里,并且在 README 里留一行说明。
6. 进阶:用 jlink 裁一个能塞进镜像的运行时
免安装版还有个隐藏价值:它自带jmods,可以裁出只含所需模块的运行时。容器镜像里塞完整 JDK 动辄三百多兆,裁完通常能压到五十兆上下,对拉取速度影响很直观。
jlink --module-path "D:\runtime\jdk11\jmods" ^ --add-modules java.base,java.logging,java.sql,java.naming,java.desktop ^ --strip-debug --no-man-pages --no-header-files --compress=2 ^ --output D:\runtime\jre11-mini几个参数值得说清楚:--module-path必须指到jmods目录本身,指到上一级会报找不到模块;--add-modules按项目实际依赖列,Spring Boot 那类应用至少要java.base、java.logging、java.naming、java.sql、java.management,少一个就是启动时的ClassNotFoundException;--strip-debug去掉调试符号,--no-man-pages、--no-header-files去掉手册和头文件;--compress=2在 11 这一代是最高压缩档,输出目录里bin、lib、conf、legal四件套齐全。
裁完必须立刻验证,别等打包进镜像才发现缺模块:
D:\runtime\jre11-mini\bin\java -version D:\runtime\jre11-mini\bin\java --list-modules第一行出版本号,第二行列出的模块数量应该和你--add-modules列的一致(会带上自动引入的依赖模块,数量略多属正常)。
最后是我每台新机器都会跑一遍的自检脚本,放在 JDK 目录旁边:
@echo off echo ==== JAVA_HOME ==== echo %JAVA_HOME% echo ==== where java ==== where java echo ==== java -version ==== java -version echo ==== javac -version ==== javac -version四段输出连起来看,能一次性定位九成的环境问题:JAVA_HOME不对、where第一行不是目标路径、两个版本号不一致,三类问题各对应一段。从那以后我每次在新机器上装完 JDK,都强制先跑一遍这个脚本再动项目,宁可多花三十秒,也不要在构建失败之后去猜是代码问题还是环境问题。希望帮到你。
本文还有配套的精品资源,点击获取