简介:JDK 1.7.0_13是Java 7系列经典开发组件,面向需要维护历史版本项目、搭建兼容运行环境的中级开发者与运维人员。它提供javac编译器、JVM运行时和完整类库,并附带javadoc、jdb、jconsole、jmap等常用工具,可覆盖编译调试、运行监控、性能分析和API文档生成等场景。这一更新版还包含性能改进、安全性增强与缺陷修复。包体共1240个文件,压缩后约79.07MB。核心以320个jar类库、178个xml配置文件、70个dll原生库和70个exe可执行程序为主,辅以properties属性文件、bat脚本及完整的时区数据库,适合离线安装、快速搭建本地Java开发环境。资源已有373人学习下载。对需要锁定JDK 7兼容性、排查历史项目问题或批量配置多台开发机的读者,这份发行包提供了接近官方结构的原始文件,便于按目录定位组件、补齐安全策略或恢复缺失配置,省去逐个下载收集的麻烦。
1. 还在用 jdk1.7.0_13 的,多半是项目在等你
如果搜索历史里还躺着 jdk1.7.0_13 这个版本号,大概率不是闲着无聊,而是面前摆着一套 2013 年前后的老系统、老中间件或者一台不敢乱动的生产服务器。jdk1.7.0_13 是 Java 7 的某个维护版本,它最大的价值不是性能有多好,而是和旧时代的技术栈咬合得严丝合缝——老框架的字节码行为、老容器的类加载逻辑、老驱动对 JDBC 版本的挑剔,这些在新版本里早就被改掉了。本文直接拆解这个版本的安装、配置、运行参数和排错路径,帮你把 java 开发环境重新立起来,适合正在接手遗留项目或者维护老服务器的人。
2. 安装与初始配置:选对 JRE/JDK 形态,再把环境变量一次配好
2.1 先分清 JDK 与 JRE:老项目经常错在只装了 JRE
jdk1.7.0_13 的安装包通常同时包含 JDK 和 JRE,但很多人在老旧 Windows 服务器上装的时候,图省事只勾了 JRE,等编译的时候才发现 javac 不存在。这里要记住一个判断标准:如果这台机器要跑编译、打包、生成代码,就必须装完整 JDK;如果只是启动一个已经打好的 jar 或 war,JRE 也能撑住,但后续排查问题会很被动。
我一般建议开发机和构建机一律装完整 JDK,因为 jdk1.7.0_13 里的 tools.jar 封装了 javac、jar、javadoc 等核心工具,部署机才考虑只装 JRE。安装包里的目录名通常是jdk1.7.0_13,装好后会看到bin、jre、lib三个关键目录,判断安装是否完整,就看bin/javac.exe和lib/tools.jar是否存在。
位数选择也是一个常见的坑。32 位 JDK 只能加载 32 位原生 DLL,64 位同理。老项目里如果有调用硬件加密狗、读卡器、打印控件的原生库,先确认这套 DLL 的位数再决定装哪个版本,否则后面跑起来就是UnsatisfiedLinkError。可以这样检查本机能否支持 64 位:
# Windows 下查看系统信息 systeminfo | findstr /C:"系统类型" /C:"System Type" # Linux 下查看内核架构 uname -m参数字段说明:uname -m输出x86_64表示系统是 64 位,输出i686或i386表示 32 位。这一步不该省,因为装错位数的 JDK 在启动时表现并不直接,往往是跑到一半才报错,排起来更耗时。
2.2 JAVA_HOME、PATH、CLASSPATH 的配置顺序与验证
环境变量是 java 开发环境里最容易翻车的一环。配置的核心逻辑是:先定义JAVA_HOME,再把%JAVA_HOME%\bin放到PATH的最前面,最后才考虑CLASSPATH。顺序错了会出现一个经典现象:java -version是新版本,javac -version却是旧版本,因为两个 bin 目录的优先级纠缠在一起。
Windows 上我习惯用批处理一次性配好,管理员权限运行时执行:
@echo off setx JAVA_HOME "C:\Java\jdk1.7.0_13" /M setx CLASSPATH ".;%%JAVA_HOME%%\lib\tools.jar;%%JAVA_HOME%%\lib\dt.jar" /M setx Path "%%JAVA_HOME%%\bin;%Path%" /M echo done逻辑说明:setx写入的是用户或系统级环境变量,/M表示写入系统级,所有用户生效。%%JAVA_HOME%%在批处理中表示延迟展开的百分号,写入注册表后才会被解析成C:\Java\jdk1.7.0_13。注意setx Path会把已有 PATH 读取后追加,但如果 PATH 太长会截断,所以我一般建议手动去系统属性里改 PATH,而不是用命令拼接。
Linux 环境下配置更直接,编辑~/.bashrc或/etc/profile:
export JAVA_HOME=/usr/local/jdk1.7.0_13 export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar export PATH=$JAVA_HOME/bin:$PATH参数说明:JAVA_HOME指向 JDK 根目录,后续很多中间件都靠它定位 JDK;CLASSPATH里开头的.表示当前目录,老程序依赖这个约定来加载相对路径下的 class 文件。配置完先source ~/.bashrc再执行java -version和javac -version,两个命令都显示1.7.0_13才算真的干净。
CLASSPATH 在 JDK 1.5 之后其实不是必需项,但 jdk1.7.0_13 时代的老脚本里大量写死%CLASSPATH%,如果不配,老程序启动时可能找不到依赖。建议还是配一份,只是路径里别有中文和空格。
3. 运行参数实战:堆内存、永久代与编码参数这样给
3.1 区分堆内存与永久代:1.7 还没有 Metaspace
Java 7 的内存模型和 Java 8 有一个显著区别:Java 7 使用永久代(PermGen)存放类的元数据、常量池和静态变量,Java 8 才用元空间(Metaspace)替换。所以给 jdk1.7.0_13 调参数时,写-XX:MetaspaceSize是完全不生效的,正确参数是-XX:PermSize和-XX:MaxPermSize。
用最简单的 Spring 项目举例,如果部署时只给了堆内存参数,没给永久代上限,类加载一多就报:
java.lang.OutOfMemoryError: PermGen space这个报错在 Java 7 时代非常常见,尤其是热部署、动态生成类、反射频繁的项目。解决思路是显式设置永久代初始值和最大值,让 JVM 启动时就预留空间,而不是等用完再扩容:
java -Xms512m -Xmx2048m \ -XX:PermSize=128m -XX:MaxPermSize=256m \ -jar app.jar逻辑说明:-Xms512m指定堆初始大小,-Xmx2048m指定堆最大值,-XX:PermSize=128m指定永久代初始大小,-XX:MaxPermSize=256m指定永久代最大大小。四者共同决定了 JVM 的可用容量范围。
参数选择上,老服务器如果物理内存是 4G,我一般给-Xms512m -Xmx1536m -XX:MaxPermSize=256m;如果是 8G 内存,堆可以放宽到 3G,永久代保持 256M 或 384M。调的过大反而会让 JVM 预留太多系统内存,导致同一台机器上其他进程吃紧。
3.2 一套通用启动参数与 GC 日志写法
老版本 JDK 的 GC 日志写法跟新版本不太一样,Java 7 用的是-XX:+PrintGCDetails配合-Xloggc,不需要 Java 8 之后的-Xlog:gc语法。我一般这样组织一个通用的启动脚本:
JAVA_OPTS="-Xms512m -Xmx2048m" JAVA_OPTS="$JAVA_OPTS -XX:PermSize=128m -XX:MaxPermSize=256m" JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xloggc:/var/log/app-gc.log" JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai" java $JAVA_OPTS -jar app.jar参数说明:-XX:+UseConcMarkSweepGC启用 CMS 回收器,对老年代响应时间敏感的应用友好,但会额外占用 CPU;-XX:+PrintGCDetails打印 GC 详情,排查内存问题时是必须项;-Xloggc指定 GC 日志输出路径。生产环境建议把日志目录和数据目录分开,避免磁盘写满影响应用。
这里有一个容易踩的细节:-Dfile.encoding=UTF-8只对 Java 运行时读写的文件编码生效,不改变javac编译时的源码编码。如果在 Linux 上编译、Windows 上部署,源码里的中文注释和字符串会在中途变乱码,这个问题放在第 4 章专门说。
3.3 服务器物理内存与堆上限的匹配经验
堆内存和永久代参数不是拍脑袋定的。我自己判断时一般看两个指标:一是服务启动时top命令里RES占了多少,二是在压测环境把-Xmx压到临界值看有没有频繁 Full GC。一个可复用的初始配置建议如下:
| 物理内存 | 堆初始值 -Xms | 堆最大值 -Xmx | 永久代最大值 |
|---|---|---|---|
| 4G | 512m | 1536m | 256m |
| 8G | 1g | 3072m | 384m |
| 16G | 2g | 6144m | 512m |
表格里的思路是给操作系统和本机其他进程留至少 25% 的内存余量。Java 7 的 JIT 编译、本地内存、线程栈还要吃一部分非堆内存,如果把-Xmx直接顶到物理内存的 80%,系统会频繁换页,GC 时间反而变长。
4. 老 JDK 避坑清单:证书、TLS、编码和残留进程
4.1 HTTPS 请求报 SSLHandshakeException 证书错误
现象:用 jdk1.7.0_13 启动的服务访问外部 HTTPS 接口,抛出javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed,但同样的接口用浏览器访问完全正常。
原因:JDK 1.7 自带cacerts信任库停留在当年,缺失 2015 年之后新 CA 机构签发的根证书。对方服务器用的证书链里有新根证书,而 jdk1.7.0_13 不认。
解决:把缺失的根证书导入 JDK 的信任库。常见做法是先用浏览器导出对方证书链的根证书为.crt文件,再执行:
keytool -import -trustcacerts -alias new_root -file root.crt \ -keystore "$JAVA_HOME/jre/lib/security/cacerts" -storepass changeit参数说明:-alias是这条证书记录的唯一标识,可自定义;-file指定要导入的证书文件;-keystore指向 cacerts 路径;默认密码是changeit,这是发行方预设的,生产环境要改掉。导入后重启服务,HTTPS 握手错误就会消失。
4.2 默认启用的 TLS 版本过低,连接不上现代服务
现象:服务启动后日志报no cipher suites in common或SSLHandshakeException: Received fatal alert: protocol_version,网络抓包发现 TLS 握手版本不匹配。
原因:jdk1.7.0_13 默认的客户端只启用 TLS 1.0 和 TLS 1.1,而很多现代服务端已经关闭了这两个老版本,强制要求 TLS 1.2。Java 7 本身支持 TLS 1.2,只是默认没开。
解决:给 JVM 加上启动参数强制指定 TLS 版本:
java -Dhttps.protocols=TLSv1.2 -Djsse.enableSNIExtension=true -jar app.jar另外可以在$JAVA_HOME/jre/lib/security/java.security文件里找到jdk.tls.client.protocols配置项,改成TLSv1.2,这样对整个 JVM 实例都生效。需要注意,部分老客户端库内部硬编码了协议,光改 JVM 参数不够,还得检查用的是什么 HTTP 客户端版本。
4.3 javac 编译中文注释乱码或直接报错
现象:在 Windows 下用 javac 编译带中文注释的源码,报错误: 编码 GBK 的不可映射字符,在 Linux 下编译同样源码却正常。
原因:javac 的默认编码跟随操作系统的区域设置。Windows 中文系统默认 GBK,Linux 默认 UTF-8。源码明明是 UTF-8 编辑的,Windows 下用 GBK 去读,中文字符对不上。
解决:编译时显式指定源码编码,并且统一整个项目链路的编码:
javac -encoding UTF-8 -source 1.7 -target 1.7 -d ./classes ./src/**/*.java参数说明:-encoding UTF-8告诉 javac 源码文件是 UTF-8 编码;-source 1.7 -target 1.7保证编译产物字节码版本是 Java 7,避免拿到新 JDK 上编译后老 JVM 无法加载。建议把这条命令固化到构建脚本里,别依赖 IDE 的默认设置。
4.4 改完 JAVA_HOME 后 java -version 还是旧版本
现象:明明把JAVA_HOME指向了 jdk1.7.0_13,执行java -version却显示一个完全不相关的版本,甚至路径不是自己配置的目录。
原因:早期安装老版本 JDK 时,安装程序会把java.exe、javaw.exe拷贝到C:\Windows\System32,而 System32 在 PATH 里的优先级高于用户配置的变量。命令解析时先找到了系统目录下的残留文件。
解决:先定位当前生效的 java 到底在哪:
where java如果输出里有C:\Windows\System32\java.exe,删掉这个残留文件,再重新打开命令行窗口执行java -version。删除前要确认系统里没有其他依赖这个路径的程序,一般老项目不会有,因为这个目录下的 java.exe 和 JDK 是完全脱钩的。
5. 多版本共存:JDK 1.7 与新版切换的脚本与 IDE 指认
5.1 共存原则:版本目录不动,只改 JAVA_HOME
很多人在同一台开发机上既要用 jdk1.7.0_13 跑老项目,又要用新版本跑新项目,最常见也最忌讳的做法是反复卸载重装。卸载 JDK 可能把注册表、公共 JRE 和 PATH 一起清理掉,让这个版本彻底废掉。正确思路是每个版本解压或安装到独立目录,互不覆盖,运行时通过 JAVA_HOME 的指向切换。
我习惯的目录组织方式:
C:\Java\jdk1.7.0_13 C:\Java\jdk8u202 C:\Java\jdk17每个目录独立存放,安装时只装 JDK 本体,公共 JRE 不装,避免干扰。切换的核心就一句话:把JAVA_HOME指向哪个目录,PATH里就让%JAVA_HOME%\bin排最前。
5.2 Windows 切换脚本:jdk7.bat 与 jdk17.bat
Windows 下写两个批处理文件,放到一个固定目录,比如C:\Scripts。切到老版本时运行jdk7.bat:
@echo off set JAVA_HOME=C:\Java\jdk1.7.0_13 set PATH=%JAVA_HOME%\bin;%PATH% java -version javac -version切到新版本时运行jdk17.bat:
@echo off set JAVA_HOME=C:\Java\jdk17 set PATH=%JAVA_HOME%\bin;%PATH% java -version javac -version逻辑说明:这两个脚本只修改当前命令行窗口的环境变量,不影响全局设置,也不会污染其他终端。如果你想让切换持久化,可以把set换成setx /M,但这样所有新开窗口都会切换,反而不方便。
脚本末尾的输出很重要:每次切换后强制看一眼java -version和javac -version,两者版本一致才算切换成功。新版 JDK 输出可能是一长串版本信息,老版本输出1.7.0_13,很好辨认。
5.3 Linux 环境准备两个软链接切换
Linux 下我不用批处理,直接维护一组软链接,切换时只需改链接指向:
# 在 /usr/local 下维护真实目录 ls -ld /usr/local/jdk* # 建立两个替代名称 sudo ln -sfn /usr/local/jdk1.7.0_13 /usr/local/jdk7 sudo ln -sfn /usr/local/jdk8u202 /usr/local/jdk8然后写进~/.bashrc:
alias jdk7='sudo ln -sfn /usr/local/jdk1.7.0_13 /usr/local/current && export JAVA_HOME=/usr/local/current && export PATH=$JAVA_HOME/bin:$PATH' alias jdk8='sudo ln -sfn /usr/local/jdk8u202 /usr/local/current && export JAVA_HOME=/usr/local/current && export PATH=$JAVA_HOME/bin:$PATH'逻辑说明:ln -sfn的-f表示强制替换旧链接,-n避免在链接指向目录时递归创建。current作为统一的入口,脚本工具都通过current找 JDK,切换时只动链接,不碰任何配置文件。
5.4 IDE 与构建工具里的 JDK 指认
很多人在命令行切换成功,但 IDE 里跑老项目仍然编译失败,问题出在 IDE 用的是自己内置的 JRE 或全局 SDK 配置。
以通用的配置习惯来说,老项目在 IDE 里需要同时确认三个位置。第一是项目 SDK,要选成 jdk1.7.0_13 对应的目录;第二是语言 Level,必须选 7,不能选 8 或 17;第三是构建工具的编译参数,如果项目用 Maven,需要在pom.xml的maven-compiler-plugin里带上:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin>参数说明:source和target分别指定源码语言版本和字节码版本,不写的话 Maven 会用其默认 JDK 版本生成字节码,老 JVM 加载时会直接提示UnsupportedClassVersionError。三处设置必须一致,少一处就可能在本地跑通、部署到老服务器时翻车。
6. 安装完成后最该做的验证:从版本号看到 JVM 进程
装完 jdk1.7.0_13,第一件事不是喊“装好了”,而是走一遍完整的验证链,确认这个环境真的能编译、能启动、能排查。我一般按顺序执行下面这组检查:
# 1. 确认 JDK 编译工具可用 javac -version # 2. 确认运行时版本 java -version # 3. 确认安装根路径正确 echo %JAVA_HOME% # 4. 确认当前 JVM 进程属于哪个版本 jps -l # 5. 用 jstack 看线程栈是否正常输出 jstack <pid> | head -20 # 6. 用 jmap 检查堆和永久代使用量 jmap -heap <pid>第 1、2 步是入门,第 3 步最容易被忽略——很多人java -version正常,但JAVA_HOME指向的是一个不存在的目录,后面所有依赖JAVA_HOME的脚本全部失效。第 4 到 6 步是给生产环境验收用的,jps的输出会带完整启动参数,能直接看到进程是不是用 jdk1.7.0_13 拉起来的。
如果jmap -heap输出里能看到PermGen相关字段,说明这个进程确实跑在 Java 7 上;如果输出的是Metaspace,说明版本没切对。老版本的jstack不需要加-F,直接对 pid 执行就能拿到线程栈,配合top -Hp能找到 CPU 占用最高的线程号,再转换成十六进制去线程栈里定位问题。
从那以后,我每次给老服务器配完 JDK 都会强制自己走一遍这六步,少一步都不放心。尤其是jps之前一定要敲echo %JAVA_HOME%确认当前终端的指向,因为十个环境问题里有七个都出在终端会话缓存了旧路径。希望帮你把 jdk1.7.0_13 的这套环境一次配稳。
本文还有配套的精品资源,点击获取