简介这份PDF教程面向需要在Eclipse中把Java工程打包成可执行JAR的开发者尤其适合涉及第三方依赖库、希望脱离IDE独立部署运行的中初级Java程序员。内容围绕Eclipse的Runnable JAR file导出方式展开讲解JVM参数在打包后失效需命令行指定、第三方库的三种处理方式、配置文件与JAR同级目录的放置规则以及通过run.bat批处理简化启动等实用细节帮助读者避开初次打包时反复查资料、试错的弯路。资源包共1个文件为单个PDF文档整体约197KB轻量易读便于随时查阅对照。目前已有2022人学习下载说明该打包场景需求普遍。读者可据此掌握包含第三方Jar包的可执行JAR生成流程理解依赖整合与外部配置的配合方式并学会用批处理脚本管理启动参数让项目在任意支持Java的环境中顺利运行。1. Eclipse 导出可执行 Jar从「能跑」到「换台机器也能跑」的那一步本地 Eclipse 里点绿三角跑得好好的爬虫换到师兄新开的虚拟机上就抓瞎——这种场景我见过太多次。原因不复杂Eclipse 的 Run Configuration 里塞了一堆-Xmx、-D参数classpath 里挂着一串第三方 jar这些在 IDE 内部是隐式生效的一旦离开 IDE 就全部失效。Eclipse 导出可执行 JarRunnable JAR file解决的正是这件事把工程字节码和第三方依赖一起塞进一个 jar配上入口类让java -jar能直接拉起来。它适合两类人一是手头有 Eclipse 老工程、不想折腾 Maven Shade 或 Gradle Shadow 的二是需要把工具类程序丢到没有 IDE 的服务器上定时跑的。这篇就把导出流程、依赖处理方式、外部配置文件、启动参数这几件事拆开讲清楚顺带把几个容易翻车的地方标出来。2. Runnable JAR file 导出机制三种依赖处理方式到底差在哪2.1 入口类与 MANIFEST 的隐式约定Runnable JAR file 和普通 JAR file 的本质区别只有一个它会在 MANIFEST.MF 里写入Main-Class字段。普通 JAR file 导出时不会问你入口类生成的包只能被别的工程当库引用Runnable JAR file 在向导里强制你选一个Launch configurationEclipse 会从这个运行配置里反推出主类全限定名写进清单文件。所以你在 Run Configuration 里配的主类是什么导出的入口就是什么——如果工程里有多个 main 方法先在 Run Configuration 里跑通你要的那个再去导出别在向导里临时猜。MANIFEST 里还有一行Class-Path它的内容取决于你选的依赖处理方式。这一点后面 2.2 会展开。这里先记住一个结论java -jar启动时JVM 只认 MANIFEST 里的Class-Path和Main-Class命令行-cp会被忽略。很多人导出后加-cp想补依赖发现没用就是踩在这条规则上。2.2 三种依赖处理方式的取舍向导第二步的Library handling有三个选项原文说「无论哪一种都不会影响使用」这话对一半——能用但包结构和后续维护成本差别很大。处理方式产物结构优点代价Extract required libraries into generated JAR第三方 jar 解压后与你的 class 混在一起单文件java -jar直接跑同名资源可能被覆盖包体积大无法单独替换某个依赖Package required libraries into generated JAR第三方 jar 原样嵌入靠 Eclipse 自带加载器读取保留依赖原始结构依赖org.eclipse.jdt.internal加载类换 JDK 或换构建工具后行为可能变Copy required libraries into a sub-folder依赖 jar 复制到 jar 同级子目录MANIFEST 写相对路径依赖可单独替换、升级必须整个目录一起拷不能只发一个 jar我一般默认选第一种理由很实际部署时只需要传一个文件scp 一条命令搞定不用担心子目录漏拷。代价是如果两个第三方包里有同名配置文件比如都带log4j.properties解压后会互相覆盖谁后写进去谁生效。遇到这种冲突就得换第三种方式把依赖摊开成子目录让每个 jar 保持独立。2.3 导出操作的可复现步骤把流程固化成可抄的步骤避免每次凭记忆点在 Package Explorer 里右键目标工程 →Export。展开Java文件夹 → 选Runnable JAR file→Next。Launch configuration下拉里选一个已经跑通的运行配置没有就先在工程上 Run As 一次生成。Export destination填输出路径比如D:\deploy\spider.jar。Library handling按 2.2 的取舍选默认第一种。勾选Save as ANT script可选方便以后命令行重复打包。Finish。导出完成后用一条命令验证入口是否写对# 查看 MANIFEST确认 Main-Class 和 Class-Path unzip -p spider.jar META-INF/MANIFEST.MFunzip -p把清单文件直接打到标准输出不用解压整个包。重点看两行Main-Class是不是你要的入口类全限定名Class-Path在第三种模式下会列出lib/xxx.jar这样的相对路径。如果Main-Class缺失说明你选的不是 Runnable JAR file或者运行配置本身没有主类。3. 外部配置文件与 JVM 参数打包后最容易翻车的两块3.1 配置文件为什么不能留在 jar 里工程里常见的conf/xx.properties、config/db.properties如果被打进 jar运行时读的是 jar 内部路径改一个数据库地址就得重新打包。正确做法是把配置目录放在 jar 同级代码里用相对路径读// 以 jar 所在目录为基准读取外部配置避免打进包内 Path baseDir Paths.get(System.getProperty(user.dir)); Path confFile baseDir.resolve(conf).resolve(app.properties); Properties props new Properties(); try (InputStream in Files.newInputStream(confFile)) { props.load(in); } String jdbcUrl props.getProperty(db.url);user.dir是 JVM 启动时的工作目录用java -jar在哪个目录下执行它就是哪个目录。所以部署结构应该是这样deploy/ ├── spider.jar ├── run.bat └── conf/ └── app.properties注意如果你在别的目录用绝对路径java -jar D:\deploy\spider.jar启动user.dir是当前 shell 所在目录不是 jar 所在目录配置就会找不到。要么先cd到 deploy 目录再启动要么代码里用ProtectionDomain反查 jar 真实路径。3.2 JVM 参数从 IDE 迁移到命令行原文提到一个关键点Run Configuration 里设的 JVM 参数打包后不再生效。原因是那些参数是 Eclipse 启动 JVM 时拼进去的跟 jar 本身无关。迁移方式就是启动命令里显式写# 初始堆 128M最大堆 256M指定外部日志配置 java -Xms128m -Xmx256m -Dlog4j.configurationfile:./conf/log4j.properties -jar spider.jar参数逐个说明-Xms128m是初始堆设小了启动快但可能频繁 GC-Xmx256m是最大堆爬虫这类内存波动大的程序别设太紧否则OutOfMemoryError来得猝不及防-D开头的都是系统属性代码里System.getProperty能读到适合传日志配置路径、环境标识这类东西。顺序上-jar必须放最后它后面跟的才是传给 main 方法的参数写在-jar前面的都会被 JVM 当成自己的选项。3.3 run.bat 的写法与双击启动Windows 下把启动命令固化成批处理双击即可运行echo off cd /d %~dp0 start java -Xms128m -Xmx256m -jar spider.jarcd /d %~dp0是关键一行%~dp0展开成批处理文件所在目录cd /d切过去这样无论从哪里双击工作目录都固定在 deploy 下3.1 里的相对路径配置才能稳定命中。start让 java 进程在新窗口跑批处理本身立刻退出不会卡住命令行。改启动参数时只动这一行不用重新打包。4. 避坑与排查导出可执行 Jar 常见的五个翻车点4.1 双击 jar 一闪而过现象双击 jar 文件黑窗口闪一下就没了看不到任何输出。 原因java -jar报错后进程立即退出错误信息来不及看。 解决别双击开命令行执行java -jar spider.jar错误堆栈会留在窗口里。常见报错是no main manifest attribute入口没写或Could not find or load main class主类名拼错或包路径不对。4.2 第三方类找不到 ClassNotFoundException现象本地 IDE 跑得好好的导出后运行报某个第三方类找不到。 原因Library handling选了Copy required libraries into a sub-folder但只拷了 jar 没拷lib子目录或者选了 Extract 模式但依赖里有 SPI 配置文件META-INF/services被覆盖。 解决确认部署目录结构完整SPI 冲突的话改用 Package 模式或者手动把META-INF/services下的文件合并。4.3 配置文件读取路径错乱现象报FileNotFoundException路径指向一个不存在的目录。 原因user.dir跟你以为的不一样见 3.1 的注意点。 解决启动前cd到 jar 所在目录或者代码里改用getClass().getProtectionDomain().getCodeSource().getLocation()反查 jar 路径再拼配置目录。4.4 内存参数没生效现象明明命令行写了-Xmx512m程序还是 OOM。 原因参数写在了-jar后面被当成 main 方法的入参传进去了JVM 根本没解析。 解决所有-X、-D参数必须放在-jar之前。用jps -v或jinfo -flags pid可以确认实际生效的 JVM 参数。4.5 换 JDK 版本后加载器报错现象Package 模式导出的 jar在另一台机器上换了个 JDK 就跑不起来报org.eclipse.jdt.internal.*相关错误。 原因Package 模式依赖 Eclipse 自带的类加载器读取内嵌 jar这个加载器跟 Eclipse 版本绑定跨环境不保证兼容。 解决要么统一 JDK 和运行环境要么改用 Extract 或 Copy 模式别依赖 Eclipse 私有加载器。5. 进阶用 ANT 脚本固化打包流程与产物校验向导点多了总会漏步骤尤其是工程依赖变动后忘了重新选入口类。Eclipse 在导出向导最后一步有个Save as ANT script勾上会生成一份build.xml把刚才的导出配置固化成可重复执行的脚本。之后打包不用再点向导命令行ant -f build.xml就行适合放进 CI 或者写个 bat 一键出包。生成的 ANT 脚本核心是jar任务关键属性值得认识!-- 节选自 Eclipse 生成的 build.xml只保留关键属性 -- jar destfiledeploy/spider.jar basedirbin filesetmanifestmergewithoutmain manifest attribute nameMain-Class valuecom.example.SpiderMain/ attribute nameClass-Path valuelib/log4j.jar lib/mysql-connector.jar/ /manifest zipfileset srclib/log4j.jar excludesMETA-INF/*.SF, META-INF/*.DSA/ zipfileset srclib/mysql-connector.jar excludesMETA-INF/*.SF, META-INF/*.DSA/ /jardestfile是产物路径basedir是编译输出目录Eclipse 默认binfilesetmanifestmergewithoutmain表示合并依赖里的清单但不覆盖主清单。zipfileset把第三方 jar 解压进来excludes排除签名文件——这一步很关键第三方 jar 带数字签名时解压后签名失效会导致SecurityException排除掉.SF、.DSA就绕开了。Class-Path属性在 Extract 模式下其实用不上但保留着不影响换成 Copy 模式时直接改这里就行。产物校验我习惯固定走两步。第一步看清单unzip -p deploy/spider.jar META-INF/MANIFEST.MF | grep -E Main-Class|Class-Path第二步跑一次空载启动确认入口和依赖都能加载java -jar deploy/spider.jar --help如果程序没有--help参数就加个-Ddry.runtrue之类的开关让它在不真正执行业务逻辑的情况下走完类加载和配置读取。这两步过了再丢到目标机器上跑基本不会出 4.1 到 4.5 那些问题。血泪经验是别信「本地能跑就行」。我早期图省事导出后直接 scp 到服务器结果因为user.dir不对配置读的是服务器根目录下的空文件程序用默认参数连了测试库跑了一晚上写脏了数据。从那以后我每次导出 jar都强制在目标目录下先cd再java -jar空跑一遍确认配置路径和依赖加载都对才敢挂后台。希望帮到你。本文还有配套的精品资源点击获取 SEO 优化官网定制响应式建站教育培训建站