简介:jdk-7u5-windows-x64-demos 对应 Java SE 7 Update 5 的 64 位 Windows 开发包,解压后得到 jdk1.7.0_05 目录,内含 JRE 运行环境,以及 javac 编译器、调试器等开发工具,适合需要搭建 Java 7 编译环境、维护旧版本项目或系统学习 Java 7 语言特性的初中级开发者。压缩包为 zip 格式,体积约 15.69MB;上游未提供文件数量与类型明细,从发行内容看,包内以 JDK 标准目录为主,开发工具与运行环境两部分齐备。资源已有 272 人学习下载。就内容而言,Java 7 引入的 switch 支持字符串、try-with-resources 自动关闭资源、钻石操作符与泛型类型推断改进、NIO.2 文件系统 API、Fork/Join 并行框架以及多异常捕获等特性,都能在该版本中实际编码验证;配合 64 位寻址与 G1 收集器,还可观察大内存场景下的运行表现,便于对照旧项目代码理解版本兼容性差异,对需要向后兼容旧系统的团队来说,是一个可直接部署的参考基线。
1. 一个装完就被忘掉的目录
jdk-7u5-windows-x64-demos 这个包,多数人是在装 64 位 JDK 7 时顺手勾上的,装完就再没打开过。它不是运行时,也不是文档,而是一批能直接编译、直接跑的官方示例源码:Swing 的自定义组件、JNI 的本地库调用、JMX 的 MBean 注册、NIO 的选择器与文件锁,几乎每个都能单独拎出来当一个最小工程看。这类东西的价值不在于“学 Java 语法”,而在于你能看到一套完整程序从入口、资源加载到线程调度的真实写法,而不是被教程截断过的片段。
先给一个反直觉的结论:这个包里绝大部分示例是纯 Java,跟 32 位还是 64 位没有半点关系,真正和 x64 强绑定的只有 JNI 那一小撮。所以别一上来就担心位数问题,先跑起来再说。
2. 拆包:demos 目录里哪几块还值得动手
拿到包后第一件事不是编译,是认清结构。JDK 7 时代的 demo 目录分区相对固定,但不同小版本之间会有增删,我见过有人拿一份整理好的清单去对照另一份包,结果对不上就以为包是坏的。正确的做法是自己先dir一遍,再决定从哪个目录下手。
2.1 目录分块与对应的技术栈
先按用途给一个粗分,方便你决定时间花在哪:
| 目录 | 主要内容 | 今天还值不值得看 |
|---|---|---|
| jfc | Swing 组件、文本编辑器、表格、字体与 2D 渲染 | 值得,Swing 在内部工具里仍然在跑 |
| applets | Applet 演示,含 2D 动画与绘图 | 参考绘图代码,运行方式已过时 |
| jni | JNI 调用与 Invocation API | 值得,DLL 那套流程十年没变 |
| jmx | MBean、监控与管理端点 | 值得,思路可直接迁移 |
| nio | Channel、Selector、文件锁 | 值得,网络编程入门材料 |
| rmi | 远程方法调用 | 了解即可,启动顺序有讲究 |
| security | 签名、策略文件、权限控制 | 概念仍然通用 |
| sound | Java Sound 的播放与采集 | 冷门但代码完整 |
| scripting | JSR-223 脚本引擎调用 | 接口层面的最小样例 |
如果你只有一两个晚上的时间,我建议按 jfc → jni → nio 的顺序看,这三块覆盖了桌面、本地库、网络三条主线,其余按兴趣挑。applets 和 rmi 可以先跳过,前者跑起来麻烦,后者在现代工程里基本被替换掉了。
2.2 先跑 jar:三行命令验证 64 位工具链
很多示例目录里已经带了打好的 jar,不用编译就能先确认环境是对的。以 jfc 下那个经典的 Swing 演示集为例,命令很短:
set JAVA_HOME=C:\Java\jdk1.7.0_05 set PATH=%JAVA_HOME%\bin;%PATH% java -version三行之后,输出里必须出现64-Bit Server VM字样。如果显示的是Client VM或者干脆没有位数信息,说明PATH里排在前面的不是这份 64 位 JDK,后面所有编译都会跑偏。确认完再执行:
cd /d %JAVA_HOME%\demo\jfc\SwingSet2 java -jar SwingSet2.jarcd /d里的/d是必须的,否则在当前盘符之外切换会失败,这是批处理里最常见的低级错误之一。java -jar走的是 jar 内的 Manifest 主类,所以不需要写 classpath,也不需要管源码在哪。窗口能弹出来、组件能拖拽、主题能切换,就说明这份 demos 和你机器上的 JVM 是配套的。
提示:
JAVA_HOME路径里不要带空格和中文。带空格的路径在某些示例的构建脚本里不会被引号包住,报错信息还特别含糊。
2.3 编译第一个源码示例:先找 main 方法
jar 能跑不代表源码能编。挑一个纯 Java、无外部依赖的示例目录,先定位入口类,别靠猜文件名。Windows 下用findstr扫一遍最快:
cd /d %JAVA_HOME%\demo\jfc findstr /s /c:"public static void main" *.java输出会直接告诉你哪个文件里有主方法。这一步看起来笨,但能省掉“我以为是 Main.java 结果是 Demo.java”的来回折腾。定位到之后,进到该示例的src目录编译:
cd /d %JAVA_HOME%\demo\jfc\某示例\src javac -encoding UTF-8 -d ..\classes *.java java -cp "..\classes;." 主类名-d ..\classes让编译产物和源码分开,避免.class文件撒得整个 src 都是;-cp里的;.是把当前目录也加进去,因为不少 Swing 示例会按相对路径读同目录下的图片和配置文件。如果启动后界面正常但缺图标、缺皮肤,八成就是资源没进 classpath,这个坑在第 5 章还会细说。
3. 用 7u5 的 javac 编译示例:编码、target 与 classpath
编译这些示例真正的门槛不在语法,而在工具链对齐。demos 里的代码是按 JDK 7 的 API 写的,有些地方会碰到当时还没被封禁的内部实现,用你机器上现装的 JDK 17、JDK 21 去编,报错会非常难看。所以第一条原则很硬:编示例就用包里这套 7u5 的 javac。
3.1 环境对齐:先确认 amd64 而不是 Client VM
java -version只能看到运行时的位数,看不到java.home指向哪里。真正确认要用属性输出:
java -XshowSettings:properties -version 2>&1 | findstr /i "java.home os.arch java.version"三个关键值:java.home应当指向jdk1.7.0_05\jre,os.arch应当是amd64,java.version应当是1.7.0_05。三者有任何一项不对,后面的编译结果都不可信。os.arch显示x86是 32 位 JVM 的典型特征,这种情况下你编出来的 class 仍然能跑,但一旦涉及 JNI 就必然崩,因为 64 位 JVM 拒绝加载 32 位 DLL。
还要确认javac和java来自同一套 JDK:
where java where javac两条输出应该在同一目录下。装过多个 JDK 的机器上,PATH里经常是java指向新的、javac指向旧的,或者反过来,症状是编译通过的代码运行时报UnsupportedClassVersionError,版本号差一截。这种情况不要试图改代码,先改PATH。
3.2 批量编译脚本与每个参数的作用
示例多的时候一个个手敲不现实。写个批处理把常见参数固化下来,注意每个参数都不是装饰:
@echo off setlocal set JAVA_HOME=C:\Java\jdk1.7.0_05 set SRC=%~1 set OUT=%~2 if not exist "%OUT%" mkdir "%OUT%" "%JAVA_HOME%\bin\javac" -encoding UTF-8 -source 1.7 -target 1.7 ^ -Xlint:-options -d "%OUT%" -cp "%OUT%" "%SRC%\*.java" if errorlevel 1 ( echo 编译失败,检查 classpath 与编码 exit /b 1 ) echo 编译完成:%OUT%参数逐个说清楚:-encoding UTF-8决定源码里非 ASCII 字符按什么解码,示例代码本身多是英文,但你自己加的注释大概率是中文,不加这条在某些终端下会直接报“编码 GBK 的不可映射字符”;-source 1.7 -target 1.7是显式钉死语言级别和字节码版本,防止有人把脚本挪到新 JDK 上跑出意外行为;-Xlint:-options只是把“source 7 已过时”这类警告压掉,不影响结果;-d和-cp同时指向输出目录,是为了让同一批源码里互相引用的类在编译期就能找到。
errorlevel判断别省。批处理不会因为 javac 失败就自动停,后面接着跑java会得到一个更难懂的NoClassDefFoundError,反而掩盖了真正的问题。
3.3 资源文件与第三方 jar 的处理
不少示例不是单个类,它依赖同目录的 properties、图片、音频,甚至依赖 demo 目录下某个共享的 jar。判断方法很直接:
dir /s /b *.jar dir /s /b *.properties先看示例根目录有没有lib之类的子目录,再看源码里getResource或getResourceAsStream的路径字符串。Swing 示例里的皮肤、图标通常走Class.getResource,它按 classpath 查找,所以资源必须和 class 在同一个 classpath 根下,或者你手工把资源目录也加进-cp。
java -cp "..\classes;..\resources;." 主类名第三方 jar 用分号追加即可,Windows 上分隔符是;不是:,这一点从 Linux 迁过来的人经常写错。如果示例的 README 里提到某个 jar 但目录里找不到,先别急着去外面找替代品,翻一遍上一级目录,很可能整个 demo 树共享一个公共 lib。
4. JNI 与 applet:64 位 DLL 和已经死掉的插件
这两块是 demos 里最容易劝退人的部分,原因完全不同:JNI 是位数和编译工具链的问题,applet 是整个运行载体没了。分开处理,别混在一起调试。
4.1 JNI 示例的完整链路:javah、gcc -m64、java.library.path
注意一个时代细节:JDK 7 还没有javac -h这个选项,生成头文件要用javah。很多照着新教程操作的人卡在这一步,以为命令写错了,其实是版本差异。最小可跑的例子长这样:
public class NativeMath { static { // 库名不带前缀和后缀,Windows 下对应 nativemath.dll System.loadLibrary("nativemath"); } public native int add(int a, int b); public static void main(String[] args) { System.out.println("2 + 3 = " + new NativeMath().add(2, 3)); } }生成头文件并编译本地库:
javac -encoding UTF-8 NativeMath.java javah -jni -classpath . NativeMath gcc -m64 -shared -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" ^ -o nativemath.dll NativeMath.c java -Djava.library.path=. NativeMathjavah -jni产出的头文件里函数签名是固定的,JNIEXPORT jint JNICALL Java_NativeMath_add,这个JNICALL在 32 位 Windows 上展开成__stdcall,在 64 位下被忽略——所以 32 位时代常加的-Wl,--add-stdcall-alias在 x64 上可以不加,加了也不影响,但不要以为它是必须的。
gcc -m64这个参数是整条链路的核心。MinGW 如果装的是 32 位版本,-m64会直接报不支持,这时候换工具链比改代码快。-I两个 include 目录一个都不能少,jni.h在第一个,jni_md.h在win32子目录下,少一个就是编译期找不到类型定义。
-Djava.library.path=.是运行时告诉 JVM 去哪找 DLL。这个属性必须在启动命令行上传,程序里System.setProperty改它是无效的,因为 native 库的搜索路径在 JVM 初始化阶段就定了。这是血泪经验,见过太多人把setProperty写在main第一行,然后对着一模一样的UnsatisfiedLinkError怀疑人生。
4.2 applet 示例的最后可用方式与改写骨架
applets 目录下的示例,现在只有一种方式能跑起来:用 7u5 自带的appletviewer。浏览器端的 Java 插件早已不被现代浏览器支持,装插件这条路走不通,也不用浪费时间找。
cd /d %JAVA_HOME%\demo\applets\某个示例 "%JAVA_HOME%\bin\appletviewer" 示例.html注意appletviewer在更高的 JDK 版本里已经被移除,所以你只能用这套 7u5 的。这也是为什么建议把整个 demos 和它配套的 JDK 放在一起,别指望用新 JDK 去跑老载体。
如果你真正想要的是里面的绘图逻辑,改写比修环境划算。Applet 到 JPanel 的映射关系很固定:
// 原 Applet 写法:init / paint / destroy public class DemoApplet extends java.applet.Applet { public void init() { /* 初始化组件 */ } public void paint(Graphics g) { /* 绘制 */ } } // 改写后:构造器 / paintComponent public class DemoPanel extends JPanel { public DemoPanel() { /* 原 init 的内容搬到这里 */ } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 必须先调用,否则背景残留 // 原 paint 的绘制代码 } }三个要点:paint改成paintComponent且方法首行必须super.paintComponent(g);init里的组件装配搬到构造器;Applet上用到的getParameter改成从配置或构造参数传入。搬完之后套一个JFrame就能跑,比折腾插件省事得多。
4.3 需要多进程的示例:RMI 与 JMX 的启动顺序
rmi 和 jmx 目录下的示例不是单进程能跑通的,顺序错一步就卡住。RMI 的固定顺序是:先起注册表,再起服务端,最后起客户端。
start rmiregistry 1099 java -cp . -Djava.rmi.server.codebase=file:/%CD%/ 服务端主类 java -cp . 客户端主类rmiregistry必须单独起一个窗口,它是个常驻进程。codebase指向的是类文件的根目录,用file:协议时路径分隔符在 Windows 上仍然是/,写成反斜杠会解析失败。
JMX 示例反过来,服务端先起并开管理端口,再用jconsole连:
java -Dcom.sun.management.jmxremote.port=9999 ^ -Dcom.sun.management.jmxremote.authenticate=false ^ -Dcom.sun.management.jmxremote.ssl=false 服务端主类 "%JAVA_HOME%\bin\jconsole"关掉认证和 SSL 只适合本机调试,别把这个参数组合带到任何对外暴露的环境里。JMX 示例本身是用来演示 MBean 注册与属性暴露的,把jconsole连上、能在 MBean 树里看到自己注册的条目,这个示例就算吃透了。
5. 避坑与排查:五个真实翻车现场
5.1 装完发现根本没有 demo 目录
现象:JDK 装好了,bin、jre都在,就是找不到demo。
原因:安装器里 Demos and Samples 是独立组件,默认不一定勾选;另外只装 JRE 的机器上永远不会有这个目录。
解决:重新运行安装程序,在组件选择里勾上示例那一项;或者单独取这个 demos 包,解压到 JDK 根目录下,目录名保持一致即可,示例不依赖安装注册表。
5.2 UnsatisfiedLinkError 与位数错配
现象:JNI 示例编译通过,运行时抛UnsatisfiedLinkError,提示里带Can't load IA 32-bit .dll on a AMD 64-bit platform。
原因:DLL 是 32 位编译器产出的,而 JVM 是 64 位。位数必须严格一致,没有兼容模式。
解决:用-m64重编 DLL;同时确认where gcc指向的是 64 位工具链。判断 DLL 位数可以用dumpbin /headers nativemath.dll看 machine 字段,x64 对应 8664。
5.3 用新 JDK 编译老示例报内部 API 错误
现象:程序包 sun.misc 不存在或com.sun.* 是内部专用 API,可能会在未来版本中被删除,编译直接失败。
原因:这些示例是按 JDK 7 的 API 面写的,部分代码碰了当时的内部实现,新版 JDK 把它们封了。
解决:换回 7u5 自带的javac。如果一定要在新 JDK 上编,只能逐个改源码替换内部 API,成本远高于直接用老工具链,不划算。
5.4 Swing 示例能起窗口但资源全丢
现象:界面出来了,但图标是空白、皮肤不生效,控制台偶尔打印getResource返回 null 的堆栈。
原因:资源文件没进 classpath。Class.getResource是按 classpath 根查找的,源码目录里的图片不会自动跟着.class走。
解决:把资源目录显式加进-cp,或者编译后手工把 properties、图片拷到输出目录对应位置。稳妥做法是编译前先看一遍源码里的资源路径字符串,按路径结构在输出目录里建同样的层级。
5.5 appletviewer 找不到或 applet 白屏
现象:appletviewer命令不存在,或者窗口开了但一片白。
原因:前者是用了更高版本的 JDK,那个工具已被移除;后者多半是 html 里的<applet>标签路径写错,或者示例本身要求文件读写权限被安全策略拦了。
解决:用 7u5 的bin目录下的appletviewer;白屏先看 html 里code和archive属性的相对路径,再考虑权限问题,涉及本地文件访问的示例在 appletviewer 里会抛SecurityException,这类示例直接走 4.2 的改写路线更省时间。
6. 把示例改成自己的骨架:一份验证清单
示例看懂了不等于会用。我的习惯是挑一个结构清晰的 Swing 示例,把包名、类名全改掉,删到只剩窗口骨架,再从零往上加自己的逻辑。删的过程中如果编译不过,说明你还没真正理清类之间的依赖;能删到只剩一个空窗口还编译通过,这套骨架才算你的。
抽取分三步走:先把入口类和主窗口分离,入口只留main和启动调用;再把界面构建拆成独立方法或独立类,所有add、setLayout集中在一处;最后把资源加载统一收口到一个工具方法里,路径只写一次。三步做完,示例就变成了可复用的模板,而不是一坨不敢动的代码。
改造完交付前,按这张表跑一遍,比凭感觉靠谱:
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| JVM 位数 | java -XshowSettings:properties -version | os.arch = amd64 |
| 编译产物版本 | javap -verbose 主类 | findstr major | major version: 51 |
| 本地库加载 | java -Djava.library.path=. 主类 | 无UnsatisfiedLinkError |
| 资源可达 | 启动后逐个点开菜单与图标 | 无空白图标、无 null 堆栈 |
| 多进程示例 | 按注册表→服务端→客户端顺序启动 | 三段日志依次出现 |
major version: 51对应 Java 7 的字节码,如果你看到 61 或 65,说明编译用的不是这套 7u5 的javac,混进了新工具链。
最后说个教训。早年我图省事,直接拿机器上现装的新 JDK 去编这些示例,报错信息看得一头雾水,改了两天源码才发现问题根本不在代码,而在工具链版本对不上。从那以后,我每次碰这种带版本烙印的示例包,都先把JAVA_HOME、where java、os.arch这三项强制走一遍,确认干净了再动手编译,省下来的时间远超这几条命令的开销。这套 demos 现在还在我硬盘里留着,偶尔要写个 Swing 小工具或者调一段 JNI,翻出来比搜教程快。希望帮到你。
本文还有配套的精品资源,点击获取