ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

IDEA 2020.3启动IllegalArgumentException怎么办

IDEA 2020.3启动IllegalArgumentException怎么办 “IDEA 2020.3 启动项目直接报java: java.lang.IllegalArgumentException”这句话我今年已经听过不下十次了。前两天还有个同事中午饭都没吃就盯着 Build 窗口那行红字发愁问我说自己什么都没改怎么一觉醒来项目就起不来了。说实话这个报错特别坑。它不像空指针、不像类找不到IllegalArgumentException字面意思是“参数不合法”可启动一个项目时到底谁给谁传了非法参数IDEA 报错窗口又往往只给一行摘要真正的堆栈被折叠在角落里很多人根本不知道去哪里看。结果就是百度一圈下来的方案五花八门要么清缓存、要么重装 IDEA折腾一下午还不一定治本。我这些年处理过不少类似的启动失败问题可以负责任地告诉你这个异常本身不值钱值钱的是它后面跟着的Caused by那一串。真正的原因可能藏在 JDK 配置、Lombok 版本、Gradle 缓存、甚至 IDEA 2020.3 这个老版本自己的插件兼容性里。这篇文章我按自己的排查习惯来写先带你搞懂问题本质再给一套能落地的定位链路最后拿出几个我实际处理过的案例做参考。如果你是 Java 开发者、正被 IDEA 启动问题卡住或者想提前避坑这篇应该能帮你省下不少时间。1. 看起来一样的报错来源完全不同的几类场景先聊个基础问题IllegalArgumentException到底是谁抛出来的按 Java 的异常设计这个异常通常由方法自己在入口处做校验发现调用方传入的参数不满足约定时主动抛出。比如某个方法要求参数不能为 null你传了 null它就炸给你看。所以在 IDEA 启动项目这个场景里我们要搞清楚的是哪一行代码在做参数校验以及它校验的是什么值。IDEA 里点下 Run 按钮之后背后其实走了一整条链路IDEA 读取项目 JDK、language level、编译器参数调用内置编译器或外部构建工具Maven/Gradle执行编译编译过程中触发注解处理器Lombok、MapStruct 等构建工具解析pom.xml/build.gradle并加载依赖IDEA 同时还会做索引更新、插件初始化、资源文件拷贝。任何一个环节吞掉了不该传的参数最终都会以java.lang.IllegalArgumentException的形式冒出来。更恶心的是IDEA 的 Build 窗口默认会把异常摘要分行显示第一行是java: java.lang.IllegalArgumentException完整堆栈得展开才能看到很多人根本没注意。基于我见过的案例启动时报这个错大概率落在这么几类来源异常出现的环节常见的真实原因特征JDK / 编译器配置SDK 路径错误、language level 与 JDK 不匹配、编译器参数非法换台电脑或重装 IDEA 后开始出现注解处理器Lombok 版本与 JDK 不兼容反射访问 JDK 内部 API 失败升级 JDK 后突然报错构建脚本解析Gradle/Maven 配置中出现非法参数比如空值、错误格式每次启动稳定复现命令行编译同样报错插件初始化IDEA 插件版本过新/过旧与 2020.3 的 API 不匹配更新某个插件后开始出现IDEA 缓存/索引缓存损坏导致编译器拿到脏数据重启、清缓存有时能好有时反复顺便提个热词里的经典例子Android 开发中常见的IllegalArgumentException: invalid token image/jpeg那是图片 MIME 类型处理时传入了不符合规范的 token跟 IDEA 本身没关系纯粹是业务代码或者资源处理逻辑的问题。还有一个梗叫“data sources cannot be empty”这是某些数据源框架在空配置时抛出的校验异常。举这些例子的意思是同一个异常名字在不同上下文里代表的完全是两码事排查的第一步永远是先分清问题发生在哪个环节。2. 先看堆栈再动手从 IDEA 日志里锁定真实元凶的排查路径遇到这种报错我最反对的就是上来就 Invalidate Caches、重装 IDEA。不是说清缓存没用而是没定位就乱试纯粹碰运气可能把现场毁了后面更难看。正确做法是沿着堆栈一层层剥。2.1 第一步把 Build 窗口的红字完整展开IDEA 的 Build 窗口报错时别只盯着最上面一行。点开那条红色信息左侧的三角形展开按钮或者直接看底部的完整堆栈。你要找的是Caused by:开头的行那才是链条的源头。举个例子之前有个项目启动报错长这样java: java.lang.IllegalArgumentException at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:xxx) ... Caused by: java.lang.IllegalArgumentException: error: cannot access annotations at jdk.compiler/com.sun.tools.javac.comp.Annotate.flush(Annotate.java:xxx)虽然同样叫IllegalArgumentException但Caused by里写的是cannot access annotations这就说明问题出在注解处理阶段而不是 IDE 参数配置。再往下翻还能看到Lombok或mapstruct的字样靶子基本就锁定了。2.2 第二步翻 IDEA 的原始日志Build 窗口有时会吞掉细节但 IDE 自己的idea.log不会。打开方式Help - Show Log in ExplorerWindows或Show Log in FinderMac。日志路径一般在配置目录的log文件夹下。在idea.log里搜IllegalArgumentException、ERROR、Caused by这些关键词能看到更完整的调用栈。特别要注意有没有Plugin相关的包名——如果堆栈里有com.intellij之外的第三方插件包比如 Lombok 插件、MyBatis 插件、某个主题插件那基本就是插件和 2020.3 的 API 不兼容导致的了。2.3 第三步脱离 IDEA用命令行验证这一步能快速区分“项目本身的问题”和“IDE 的问题”。在项目根目录打开终端执行等价构建命令。Maven 项目跑mvn clean compileGradle 项目跑gradlew clean compileJava。命令行也报一模一样的错问题在项目本身和 IDEA 无关。优先查依赖版本、JDK 配置、注解处理器版本。命令行编译通过只有 IDEA 里报错问题出在 IDEA 侧。要么是 IDEA 内置编译器参数、要么是插件、要么是缓存/索引。这一步我几乎每次都会做因为它能直接砍掉一半的排查分支省下的时间远超那两分钟。2.4 第四步新建空项目验证全局配置如果命令行编译没问题、IDEA 里依然报错那下一个变量就是 IDEA 的全局配置。新建一个最简单的 Java 项目只配置项目 SDK什么都不加直接编译运行空项目正常说明你的全局配置整体没问题问题收窄到当前项目的.idea配置或依赖空项目也报错说明 IDEA 全局层就有问题比如默认 JDK 路径坏了、全局插件干扰、内置 JBR 出问题。这个步骤看起来笨但效率奇高。我在处理“IDEA 自动关闭 启动异常”这类问题时经常用能非常快地判断是局部问题还是全局问题。3. 我处理过的四个真实 CaseJDK、Lombok、Gradle 和 IDEA 缓存套话讲完上实战。下面这四个案例都是我实际遇到过的现象清一色是java.lang.IllegalArgumentException但根因完全不同。我保留关键细节把定位思路完整写出来。3.1 Case 1JDK 路径带空格引发的编译器参数校验失败现象同事拉了个老项目到新电脑IDEA 2020.3 里配置好 JDK 后启动报错Caused by指向javac的 API提示某个路径参数非法。排查过程命令行编译正常IDEA 内编译失败说明问题出在 IDEA 传给编译器的参数上。打开Project Structure - SDKs发现他配的 JDK 路径是C:\Program Files\Java\jdk1.8.0_281路径里带空格。有的编译器插件对于带空格的路径处理不严谨拼接参数时没有加引号传给 JDK 的javac后路径被拆成两段参数校验直接不通过抛IllegalArgumentException。解决方式把 JDK 换到无空格路径比如C:\Java\jdk1.8.0_281同时在Project Structure - Project里重新选一次 SDK再重启 IDEA 让它重新加载。改完立刻就好了。经验Windows 上安装 JDK 真别图省事用默认目录带空格的路径长期用下来迟早出幺蛾子。不只是 IDEA很多命令行工具都对空格路径不友好。3.2 Case 2Lombok 版本过旧JDK 升级后触发反射校验异常现象项目原来跑在 JDK 8 上一切正常后来因为某个依赖要求把项目 JDK 升到了 JDK 11IDEA 里启动直接报java.lang.IllegalArgumentExceptionCaused by里能看到lombok字样。排查过程先看依赖树里 Lombok 的版本赫然是1.16.x——这个版本在 JDK 8 时代没问题但 JDK 9 之后模块系统封闭了 JDK 内部 API老版本 Lombok 靠反射访问com.sun.tools.javac内部类时就会失败。IDEA 内置编译器调用 Lombok 注解处理器时处理器自己抛了非法参数最终经 javac 包装后显示为IllegalArgumentException。解决方式把 Lombok 升级到1.18.20以上具体版本取决于你用的 JDK 大版本然后在File - Settings - Build, Execution, Deployment - Compiler - Annotation Processors里确认勾选了启用注解处理。如果升级后仍有问题还要在启动配置的 VM options 里加--add-opens jdk.compiler/com.sun.tools.javac.codeALL-UNNAMED --add-opens jdk.compiler/com.sun.tools.javac.compALL-UNNAMED经验JDK 版本升级从来不只是改个 SDK 路径那么简单。Lombok、MapStruct、QueryDSL 这些注解处理器全都对 JDK 版本高度敏感升级前先查好对应版本的兼容矩阵。3.3 Case 3Gradle 缓存损坏构建配置拿到非法参数现象一个 Gradle 项目某天开始一启动就报IllegalArgumentException每次报错位置都在同一个 Task 的配置阶段。清理build目录没用执行gradlew clean也没用报错稳定复现。排查过程命令行执行gradlew compileJava发现同样报错确认问题在项目/依赖层。但仔细看build.gradle并没有明显语法问题。后来打开项目下的.gradle目录发现里面有大量缓存配置和旧的 task history。Gradle 的配置缓存configuration cache或构建缓存如果写入时崩溃下次构建读到脏数据某些参数就变成了空值正好命中任务参数的合法性校验。解决方式先执行gradlew --stop然后删除项目根目录下的.gradle文件夹和build目录重新执行同步。如果项目启用了 configuration cache还要在gradle.properties里临时加上org.gradle.configuration-cachefalse做验证。清完重跑问题消失再重新打开缓存。经验Gradle 的缓存不是圣杯它也可能损坏。遇到“改动没作用、报错顽固”的情况清.gradle常常比清 IDEA 缓存更管用。另外IDEA 2020.3 自带的 Gradle 支持版本偏旧如果项目用了特别新的 Gradle 版本也会出现兼容性问题这个在后面章节细说。3.4 Case 4IDEA 索引损坏编译器拿到了脏配置现象项目原本正常某天 IDEA 毫无征兆地开始抛异常Caused by指向 IDEA 自己的项目结构组件。重启 IDEA 后报错依然存在。排查过程命令行编译一切正常说明项目本身没问题。检查了 Project Structure 里的配置SDK 和 language level 也都正确。最后发现是 IDEA 的项目索引和缓存损坏导致它在构建时读到了过期的模块配置其中某些参数的值变成了 null。解决方式执行File - Invalidate Caches / Restart勾选清除系统缓存和本地历史记录重启后等 IDEA 重新索引。这一步做完问题解决。经验IDEA 的缓存机制在 2020.3 这个版本还不算特别稳定尤其频繁切换分支、改动依赖之后索引偶尔抽风。Invalidate Caches 不是万能药但它是所有排查手段里成本最低的一个适合在确认项目本身没问题之后立刻尝试。网上热词里还有个“idea自动关闭”很多也是这个原因——缓存损坏导致 IDEA 内部组件跑飞间接触发崩溃或异常。4. IDEA 2020.3 这个版本自身埋的雷插件冲突与源码兼容坑老实说IDEA 2020.3 发布到现在已经不年轻了但它依然是很多团队的“主流版本”尤其是一些老项目组不愿意升级 IDE。这篇既然标题带上了 2020.3我单独开一章讲这个版本的“版本病”。4.1 插件版本和 IDE 版本不匹配是重灾区2020.3 对应的 IntelliJ Platform 版本号是203.x后来的插件很多都按更新的平台 API 编译。IDEA 对这种插件有一个向下兼容机制但 2020.3 本身是 JetBrains 平台大规模调整 UI 和插件 API 的过渡版本。有些插件作者只在最新版上测试发布时没有声明兼容下限IDEA 也会尝试加载。加载后插件初始化代码调用了新版本才有的 API或者向某个组件传入了旧版本不支持的参数就直接抛IllegalArgumentException。常见场景升级了 Lombok 插件、MyBatisX、某款主题插件重启 IDEA 后项目编译报错禁用插件后恢复。排查方式看idea.log里有没有插件包名或者直接用二分法禁用所有第三方插件逐个试。在 2020.3 上我的建议是插件够用就行不要盲目追新。一个插件能用就别手痒升级这个版本的 API 兼容能力确实有限。4.2 内置 Kotlin 插件版本偏旧Kotlin 项目选择性地踩坑2020.3 内置的 Kotlin 插件版本在1.4.x左右如果你打开的项目用了新版 Kotlin比如1.6IDEA 内置编译器在解析 Kotlin 注解或JvmDefault等属性时可能遇到不认识的元数据抛参数异常。第一次处理这类问题时我排查了半天最后发现只要在 Project Structure 里把项目的 Kotlin 编译器指向自己下载的 Kotlin 插件版本问题就消失了。经验2020.3 想跑 Kotlin 新版本项目最简单的方案不是装新版 Kotlin 插件硬塞而是给这个老 IDE 留一个能接受的项目不要强行让它理解新时代语法。Kotlin 项目还是建议用新一点的 IDE。4.3 不要用“特殊手段”激活历史版本下载要走官方渠道网络热词里关于安装、激活的内容很多但这里我认真说一句IDEA 2020.3 这个版本官方已经不再做功能更新与其用各种来路不明的安装包和激活工具安全性没法保证而且很容易引入 DLL 劫持、广告插件干扰 Java 进程参数不如做两件事如果项目团队需要复现旧环境去 JetBrains 官网的历史版本页面下载正版安装包如果有预算或符合社区版使用场景直接升级到新版 IDEA Community / Ultimate 试用或订阅。我在帮人处理启动异常时不止一次发现“IDEA 安装目录被塞了莫名其妙的第三方插件/破解补丁”这些东西直接污染了编译器参数传递。遇到这种情况我通常建议备份配置后全新安装官方版问题一了百了。这里只讲技术风险不做任何评判。5. 修复之后的事把编译器参数、构建配置、插件版本固定成可复现的工程标准报错解决了故事就结束了吗并没有。很多项目在一个人电脑上修好了换个人、换台电脑又炸了。根子在于 IDEA 的项目配置文件、JDK 路径、编译器选项在各人机器上“各写各的”没有一个统一标准。我建议按下面的思路把环境固化下来。5.1 固定 JDK 路径和语言级别在项目.idea/misc.xml里IDEA 会记录project-jdk-name和languageLevel但这个配置只对本地有效。最好在项目文档里明确写出要求的 JDK 大版本和小版本并约定安装路径风格尤其 Windows 下避免空格。在Project Structure - Project里确认语言级别和 JDK 一致。比如 JDK 11 配 language level 11不要配成 8 或 16。编译器参数不一致是IllegalArgumentException的常见诱因这个配置必须和实际 JDK 完全对应。5.2 在构建脚本里锁定依赖插件的版本Maven 项目在pom.xml的dependencyManagement里统一锁版本Gradle 项目在gradle.properties或dependencies.gradle里统一版本变量。重点锁这几个Lombok 版本MapStruct 版本编译器插件版本maven-compiler-plugin或 Gradle Java 插件如果用了 Kotlin锁定 Kotlin 插件版本版本锁定之后同一个项目在不同机器上解析出来的依赖树是一致的很多“我这正常他那报错”的问题根本不会出现。5.3 把 JVM 参数写进可复现的配置里前面提到 JDK 11 场景下可能需要--add-opens这种参数别只在 IDEA 启动配置里手填。更好的方式是Maven 项目配置maven-compiler-plugin的compilerArgsGradle 项目在tasks.withType(JavaCompile)里配置options.compilerArgs。这样不依赖 IDE命令行构建也是同一套参数。IDEA 在同步项目时会读构建脚本的编译器配置启动时就不容易因为 IDE 侧配置和命令行不一致而踩坑。5.4 把“命令行构建验证”变成默认操作个人习惯任何一次启动报错都可以按这个顺序来——先看堆栈再在命令行跑构建然后才碰 IDEA 配置。团队协作时我也建议大家遇到诡异问题先跑一次mvn compile或gradlew compileJava把结果截图甩群里。这个动作能快速过滤环境问题省掉大量来回沟通。5.5 如果长期受困认真考虑升级 IDEAIDEA 2020.3 处理老项目确实轻快但如果你想用新版 Spring Boot、新版 Kotlin、更智能的 AI 辅助插件热词里也有人搜 IDEA AI 插件那建议换到较新的 2022.3 或 2023 版本。新版本不仅对 Java 新版本支持更好内部的编译器调用链路也重构过很多老版本里莫名其妙的参数异常在新版里基本绝迹了。如果你的团队还在统一用 2020.3那至少要做到插件版本、JDK 版本、构建工具版本“三锁定”别让任何一环游离在标准之外。我自己处理这类问题多了最大的感受是java.lang.IllegalArgumentException就像一扇门上的同一把锁钥匙却有一大串。只看锁孔永远配不出钥匙必须先看清门后面是哪条链路在运行。把排查顺序固定下来比记住任何一条具体的解决方案都管用。希望这篇能帮你少走几个小时的弯路。
返回列表