资讯详情

资讯详情

IDEA+Maven编译乱码?一文详解编码链路与彻底解决方案

做 Java 开发这些年IDEA Maven 编译时控制台乱码这个问题我至少帮同事排查过几十次。说它是小问题吧真要彻底解决得把源码编码、编译编码、JVM 进程编码、控制台显示编码这一整条链路全部捋顺少一个环节都不行说它复杂吧其实绝大多数场景就是编码约定不一致改几处配置就能搞定。今天这篇就当是我的排查笔记把思路、配置和踩过的坑一次性写全。文章主要面向 Windows 中文环境下用 IDEA 做 Java 开发的读者包括刚入行的新手以及被项目里各种编码历史问题折磨已久的老手。只要你按照后面的清单一步步对齐基本能彻底告别这类乱码。1. 先搞清楚乱码到底卡在哪一环编码链条拆解1.1 一段文字从源码到控制台要经过哪些编码转换很多人遇到乱码的第一反应是“改 IDEA 的编码设置”但改完发现该乱还是乱原因就是没搞懂数据到底经过了多少个环节。我习惯把它拆成一条链路来看。一条普通的中文信息从你写在.java文件里到最终显示在 IDEA 控制台至少要经过这些环节源码文件本身的存储编码。也就是.java文件以什么字节序列存在磁盘上IDEA 右下角一般会显示当前文件的编码比如 UTF-8编译时 javac 读取源码使用的编码。这个由 Maven compiler 插件配置或 JVM 默认编码决定Maven 进程自身 JVM 的默认编码。Maven 本质也是跑在 JVM 里的程序它的日志输出、文件读写都会受到 file.encoding 影响程序运行时输出中文所采用的编码。System.out 输出字节时PrintStream 用的编码来自运行进程的默认编码IDEA 控制台窗口用什么样的编码去解码收到的字节流。打个比方这一段文字就像一个快递包裹每一站都需要物流单号来识别。如果某站拿错单号包裹就会被送到错误的地方。编码问题也一样数据本身没有坏是“读取规则”对不上。你看到乱码本质上就是某一站的解码规则和上一站的编码规则不一致。所以“乱码”永远不是一个点的问题而是链条的问题。这也是为什么单改一个设置往往不能根治。1.2 JDK 版本变了乱码规则也变了这个因素很多老项目容易忽略。如果你用的是 JDK 8、JDK 11或者 JDK 17在没有显式指定编码的情况下JVM 默认使用操作系统平台的编码。Windows 中文版默认就是 GBK。但从 JDK 18 开始JEP 400 把 JVM 的默认字符集改成了 UTF-8。也就是说同样一段代码同一套配置你从 JDK 8 切到 JDK 21 后可能“莫名”就不乱码了。这不是 IDEA 自动帮你修好了而是 JVM 默认行为变了。反过来也说明一个问题如果团队里有人用 JDK 8有人用 JDK 21即便代码相同、提交相同控制台输出的编码表现也可能不一样。很多人遇到“同代码在我这乱码在同事那里不乱码”的诡异情况一大半原因是 JDK 版本或系统区域设置不同。所以排查时第一步就应该确认当前项目实际使用的 JDK 版本而不是上来就改配置。1.3 Windows 中文版的“历史包袱”Windows 的命令行工具包括 cmd、批处理脚本、老版本的控制台程序默认代码页经常是 936也就是 GBK。很多老工具输出的中文日志都是 GBK 编码。而 IDEA 内部控制台、现代终端工具默认更倾向于 UTF-8。这就会造成一个典型现象同一个 Maven 项目在 cmd 里运行mvn clean compile输出的中文可能正常但放到 IDEA 的控制台里跑中文全变成乱码。原因是 Maven 进程以 GBK 输出日志IDEA 控制台却按 UTF-8 去解码。所以面对乱码你必须先回答一个问题是只在 IDEA 里乱还是在 cmd、PowerShell 里也乱这个初步判断直接决定了后面你该改哪里。2. 全局层面的编码统一配置IDEA Maven 基础设置2.1 IDEA 的 File Encodings 三件套IDEA 的编码设置分散在好几个地方很多人只改了 Project Encoding结果不够用。最基础的是这里Settings → Editor → File Encodings。打开这个页面后你会看到几个关键项Global Encoding全局编码影响所有没有单独指定编码的项目文件Project Encoding当前项目的编码这个是最重要的Properties Files专门针对.properties文件的编码在页面下方或 IDE 相关设置里还有 IDE Encoding 和 Console 编码项。我的建议是Global、Project、Properties Files 三项全部设置成 UTF-8。很多人只改 Project Encoding但 Global Encoding 如果不一致某些新文件或 IDE 创建的配置文件还是会以别的编码保存后续埋坑。Properties Files 这一项也别忽略。项目里经常有application.properties、messages.properties这类文件里面写了中文。IDEA 在这里有一个“Transparent native-to-ascii conversion”的开关如果你勾选了IDEA 会把 properties 里的中文自动转成\uXXXX形式的 ASCII 内容保存这样文件本体是安全的不会因为编码不一致被破坏。我个人的习惯是打开这个选项虽然查看时有点不方便但至少不会出现“properties 保存后中文全变问号”的坑。除了 File Encodings 页面新版 IDEA 还会在同一个页面下方提供 Console 编码设置。如果没有找到可以到Settings → Editor → General → Console里看不同版本位置略有差异但思路都一样把控制台显示编码也固定成 UTF-8。2.2 Maven 构建编码pom.xml 里必须写死很多情况下IDEA 这边的验证编码已经设成 UTF-8 了源码文件也显示 UTF-8但 Maven 编译时依然乱码。问题就出在 Maven 本身并没有拿到“请用 UTF-8 编译”的指令。Maven 在 Windows 中文系统上如果 pom.xml 里没有显式声明编码相关插件会默认采用系统编码也就是 GBK。javac 会按 GBK 去读你的 UTF-8 源码文件导致中文字符串直接变乱码甚至编译报错。解决办法是在 pom.xml 的properties节点里写死编码properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding project.reporting.outputEncodingUTF-8/project.reporting.outputEncoding maven.compiler.encodingUTF-8/maven.compiler.encoding /properties这三项分别影响project.build.sourceEncodingMaven 读取和处理源码、资源文件时使用的编码也影响 maven-resources-plugin 的资源复制与过滤行为project.reporting.outputEncoding影响 Javadoc、测试报告等生成内容的编码maven.compiler.encoding传给 maven-compiler-plugin 的编译编码参数等价于 javac 的-encoding参数。如果你的项目里已经显式配置了 maven-compiler-plugin也可以在插件配置里加encodingUTF-8/encoding效果相同。不过我更推荐在 properties 里统一声明代码更简洁团队维护的时候一眼能看到。2.3 为什么统一用 UTF-8而不是“跟着系统走”有人会问既然 Windows 默认是 GBK那为什么不用 GBK反而能避免乱码现代开发工具链对 UTF-8 的支持已经非常普及。Git 仓库默认也是 UTF-8 语义Linux、Docker 容器、CI 构建环境几乎都默认 UTF-8。如果你在 pom 里写死 UTF-8至少能保证同一份代码在 Windows、macOS、Linux 上编译行为一致。GBK 的问题在于它属于“本地编码”换一台英文系统或 Linux 服务器字符集就变了。团队协作时一个统一的标准编码非常重要。UTF-8 就是目前最通用的标准。但这里有一个老项目改造时必须注意的坑如果项目里大量源码文件本身就是 GBK 存储的你直接把 pom 改成 UTF-8反而会让原本好好的中文全部变成乱码。正确做法是先把所有源码文件确认并转换成 UTF-8再改 pom。转换前最好用 Git 提交一个备份节点方便回溯。3. 卡在 Maven 进程和控制台之间运行时编码设置3.1 Maven Runner 的 VM Options这一步很容易被忽略如果 pom.xml 里已经写死了 UTF-8但 IDEA 里跑 Maven 还是乱码那问题往往出在 Maven 进程本身的 JVM 参数上。IDEA 里执行 Maven 命令本质上会拉起一个新的 Java 进程。这个进程的默认字符集如果没有被显式指定在中文 Windows 上就是 GBK。即便 pom 里设置了 sourceEncoding某些插件在输出日志时依然可能使用 JVM 默认编码导致控制台显示乱码。打开Settings → Build, Execution, Deployment → Build Tools → Maven → Runner在 VM Options 里加上-Dfile.encodingUTF-8这一步非常关键。很多教程只会告诉你改 File Encodings结果改了之后发现 Maven 输出日志还是乱码就是因为这个 Runner 的 JVM 参数没设置。顺手提一句MAVEN_OPTS 环境变量对 IDEA 内置的 Maven 运行器基本不生效因为 IDEA 不是通过命令行调用 mvn 的而是直接在自己的 Runner 里加载 Maven 运行时。所以不要把希望寄托在 MAVEN_OPTS 上要改就改上图里的 VM Options。如果这样还不够可以在 Runner 的 Environment variables 里再加一个JAVA_TOOL_OPTIONS-Dfile.encodingUTF-8。需要注意的是设置 JAVA_TOOL_OPTIONS 之后进程启动时会打印一行Picked up JAVA_TOOL_OPTIONS: -Dfile.encodingUTF-8这是正常现象不用管它。3.2 IDEA 控制台要以 UTF-8 渲染改完 Maven Runner 的 VM Options输出到控制台的字节流已经变成 UTF-8 了但如果 IDEA 控制台还在用 GBK 解码照样乱码。所以还要回过去确认控制台本身的编码。新版 IDEA 里Settings → Editor → File Encodings页面下方通常有一个 Console 下拉框把它也设置成 UTF-8。如果你的版本没有这个选项可以检查Settings → Editor → General → Console里面一般有 Default Encoding 配置项。还有一个更彻底的做法修改 IDEA 自身的 JVM 参数。菜单Help → Edit Custom VM Options打开后加这两行-Dfile.encodingUTF-8 -Dconsole.encodingUTF-8保存后重启 IDEA。这样整个 IDE 的渲染和输出都会尽量向 UTF-8 靠拢。不过需要提醒的是修改 IDEA 自身的 file.encoding 会影响到 IDE 全局行为包括缓存、日志、插件输出。一般情况下不建议随便加只有当你确认 Maven、控制台都设置正确但仍然乱码时再把它当作最后手段。3.3 用 cmd / PowerShell 跑 mvn 时乱码怎么办如果你不是在 IDEA 里跑 Maven而是在命令行直接执行mvn clean compile那情况又不太一样。cmd 默认代码页如果是 936而 Maven 输出的是 UTF-8控制台会以 GBK 解读 UTF-8 字节中文自然乱码。最简单的解决办法是先切换代码页chcp 65001然后执行 Maven 命令。这个操作只在当前命令行窗口生效不会影响系统全局。PowerShell 里还可以这样设置输出编码[Console]::OutputEncoding [System.Text.Encoding]::UTF8如果你希望团队里的所有人都能避免这个问题可以在项目的根目录放一个小脚本比如mvn-utf8.cmd内容大致是echo off chcp 65001 nul mvn %*这样团队成员直接用mvn-utf8.cmd clean compile就能避开乱码不用每个人都去背 chcp 命令。3.4 编译通过但日志输出乱码这是另一个问题还有一种很常见的场景编译不报错IDEA 控制台里编译日志也正常但程序一运行System.out 输出的中文全是乱码。这个问题的根源和上面说的编译期不一样它更多是运行期 JVM 编码或日志框架编码的问题。如果你的项目使用 Logback默认情况下 ConsoleAppender 会使用系统平台编码输出Windows 上就是 GBK。但 IDEA 控制台按 UTF-8 显示于是中文乱码。解决办法是在 Logback 的配置里显式指定字符集appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder charsetUTF-8/charset pattern%d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n/pattern /encoder /appenderLog4j2 也类似在 Console Appender 的 PatternLayout 里配置charsetUTF-8。如果是直接用System.out.println输出中文那就要确保运行程序的 JVM 编码是 UTF-8。在 IDEA 的运行配置也就是 Run/Debug Configurations 里也可以给对应 Application 的 VM options 加上-Dfile.encodingUTF-8。本质上和 Maven Runner 是同一个思路让 JVM 进程的默认编码对齐成 UTF-8。这里特别想强调一点一定要分清楚“编译期乱码”和“运行期乱码”。我见过不少人折腾了半天 pom.xml结果发现编译日志正常是自己项目里的 Logback 没配置 charset。方向错了配置改再多也没用。4. 实操从零到干净的编译控制台完整配置流程4.1 先定位是哪一类乱码动手改配置之前我强烈建议你先做一次快速定位避免“闭着眼睛改设置”。你可以写一个最简单的 Java 类public class EncodingCheck { public static void main(String[] args) { System.out.println(中文测试); System.out.println(file.encoding System.getProperty(file.encoding)); System.out.println(sun.jnu.encoding System.getProperty(sun.jnu.encoding)); } }把它放到项目里先用 IDEA 直接运行。如果输出中文正常但file.encoding是 GBK说明当前运行环境是中文 Windows 默认配置。如果中文本来就是乱码那就可以直接判断是运行期编码不对。再观察编译阶段的日志如果 Maven 编译时插件输出的中文全部乱码而你的源码运行输出正常那多半是 Maven 进程编码的问题如果源码里的中文注释都变成乱码那大概率是 javac 读取源码时用了错误的编码。这一步看起来简单但能帮你省掉大量走弯路的时间。我自己的经验是90% 的乱码问题靠这一步就能确定排查方向。4.2 一步步配置清单可直接照抄假设你已经完成了上面的定位接下来给你一份可以直接照抄的完整操作清单。这是一套我认为最稳妥的组合确认项目 JDK 版本。如果项目跑在 JDK 17 及以下且操作系统是 Windows 中文版乱码概率最高如果项目已经升级到 JDK 18默认 UTF-8但老项目还是要按下面步骤统一。打开Settings → Editor → File Encodings把 Global Encoding、Project Encoding、Properties Files 的编码全部设置为 UTF-8同时检查 Console 编码是否也为 UTF-8。如果有 IDE Encoding 的选项也一并设成 UTF-8。检查项目里现有的.java和.properties文件实际编码。在 IDEA 右下角可以看到当前文件编码如果有文件显示为 GBK可以点击并选择 Convert to UTF-8。这一步要小心转换前先确认文件内容显示正常最好提前提交一次 Git。在 pom.xml 的properties中加入properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding project.reporting.outputEncodingUTF-8/project.reporting.outputEncoding maven.compiler.encodingUTF-8/maven.compiler.encoding /properties如果项目里有显式配置 maven-compiler-plugin检查 configuration 里的 encoding 是否为 UTF-8有些老项目会在里面写死 GBK。确认后保存 pom在 IDEA 右上角 Maven 面板点击刷新按钮也就是 Reload All Maven Projects确保配置重新加载。打开Settings → Build, Execution, Deployment → Build Tools → Maven → Runner在 VM Options 里填写-Dfile.encodingUTF-8。执行一次mvn clean compile观察控制台输出。如果中文正常了说明问题已经解决。如果依然乱码继续看下面的排查部分。这套流程我帮人处理过很多次绝大多数项目到第 6 步就能看到明显效果。第 7 步如果依然有问题那就不是常规配置问题需要再往下深挖。4.3 系统级 UTF-8 开关要不要开有时候会遇到一种顽固情况IDEA 和 Maven 配置都设置好了但某个工具或者某个老脚本输出还是 GBK导致从外部拿到的日志文件、命令行输出依然乱码。Windows 10/11 提供一个系统级开关控制面板 → 区域 → 管理语言设置 → 更改系统区域设置 → 勾选“Beta: 使用 Unicode UTF-8 提供全球语言支持”然后重启电脑。这个开关的作用是把系统默认字符集切到 UTF-8很多与控制台、文件路径相关的乱码问题会从根上消失。但我个人不建议在日常开发机上轻易开启副作用比较明显一些老版本软件尤其是中文 Windows 下开发的国产工具可能会出现界面文字乱码或显示异常GBK 编码的历史文件、日志打开后会变成乱码某些依赖系统 Locale 的脚本行为可能改变。我一直把系统级 UTF-8 开关当成“最后手段”而不是首选方案。如果是团队协作环境更不应该为了某个人的问题去强制系统设置。正确顺序应该是项目统一 UTF-8 → IDEA 配置统一 → Maven Runner 统一 → 系统开关兜底。5. 常见问题速查与排查技巧5.1 典型场景速查表下面整理了几个我实际工作中反复遇到的典型场景你可以直接对照排查现象可能原因处理方法编译插件输出中文乱码英文正常Maven 进程 JVM 默认编码不是 UTF-8Maven Runner 的 VM Options 加-Dfile.encodingUTF-8编译日志正常运行程序后 System.out 输出乱码运行 JVM 编码不是 UTF-8或日志框架没指定 charsetRun Configuration 的 VM options 加 UTF-8Logback/Log4j2 配置 charset源码里的中文注释乱码javac 读取源码时使用的编码与文件实际编码不符确认源码文件实际编码转换文件后统一 UTF-8在 pom 里写死 sourceEncodingproperties 文件中文乱码Properties Files 编码设置不对File Encodings 里单独设置 Properties Files 为 UTF-8cmd 里跑 mvn 乱码IDEA 里正常命令行代码页与 Maven 输出编码不一致执行chcp 65001再运行 mvn同一套代码同事不乱码你乱码JDK 版本、系统区域设置或 IDEA 版本不同对比 JDK、系统区域、IDEA 编码设置改了 pom 后配置没生效没有重新加载 Maven 项目IDEA 里 Reload All Maven Projects这张表不是标准意义上的“速查全部”但覆盖了我见过的大部分场景。如果你遇到的现象不在表里大概率还是链条里某个环节没对齐继续用第 5.2 节的思路排查。5.2 排查乱码的“三板斧”我把我自己总结的排查思路叫做“三板斧”遇到乱码就往这三点上套。第一板斧确认乱码是在 IDEA 内还是 IDEA 外也乱。如果 cmd、PowerShell、甚至文本编辑器打开同一份日志都是乱码那问题大概率出在产生日志的一方Maven 或运行中的程序。如果外部正常只有 IDEA 控制台乱码那就是 IDEA 控制台解码编码的问题。第二板斧确认是编译日志乱码还是运行程序后的输出乱码。编译日志乱码先查 Maven Runner 和 pom 编码运行输出乱码先查 Logback/Log4j2 charset 和 Run Configuration 的 VM options。这两个方向的配置项完全是两套混在一起排查效率很低。第三板斧确认配置改动之后是否重新加载。pom.xml 改了一定要在 Maven 面板点刷新IDEA 设置改了有些需要重启 IDE 才生效。磨刀不误砍柴工不要改了配置马上跑报怨“没用”很可能只是没生效。在实际操作中还有一个非常实用的命令可以快速查看当前 Java 进程的实际编码java -XshowSettings:properties -version 21 | findstr encoding在 IDE 的终端里运行能直接看到 file.encoding 和 sun.jnu.encoding 的值。这两个值一个管文件读写一个管文件名和路径。如果 file.encoding 显示的不是 UTF-8说明进程的默认编码还是系统编码需要按上面的方式显式指定。5.3 终极兜底在项目里统一声明 JVM 编码如果公司项目由公共父 pom 统一管理不允许随便改父 pom 里的编码配置那在 IDEA 里通过 Runner VM Options 和 Run Configuration 的 VM options 指定 UTF-8是目前最不侵入代码库的办法。它的好处是只影响当前开发环境不改变仓库内容也不会影响同事。但如果你是项目负责人或者有权限调整构建配置我还是建议把编码声明写进父 pom 或项目 pom。这样才能保证新成员克隆项目后第一次跑 Maven 就处于正确配置中不用靠“每人手动改 IDEA 设置”来维护。我见过太多团队是这样的状态项目能编译是因为老成员每个人电脑里都配过了新成员入职第一天就开始乱码然后群里有人远程指导一步步改。这种模式的本质是“隐性配置”非常消耗团队精力。与其这样不如在 pom 里写死编码一劳永逸。最后再说一个我自己的经验。早期我排查乱码时总喜欢先去翻 IDEA 的设置其实很多问题的根源不在那里。后来我养成一个习惯遇到乱码先写个测试类看 JVM 实际编码再判断是不是 Maven 进程的问题。一次排查下来通常 10 分钟就能锁定方向。编码问题看着烦本质就是“链条上某一环不一致”。只要把源码编码、编译编码、进程编码、控制台展示编码全部统一成 UTF-8乱码基本就和你无缘了。希望这篇笔记能帮你少走几次弯路。刚接触这块的朋友按我第 4 节的清单走一遍今晚就能睡个安稳觉。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →