news 2026/4/3 4:13:36

Pagehelper触发 JVM 类校验失败,Idea 却因 -noverify 藏了雷

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Pagehelper触发 JVM 类校验失败,Idea 却因 -noverify 藏了雷

问题现象

最近一个老的微服务引入了page-helper 6.0版本的 jar 包之后,微服务发布到环境上去之后直接启动不起来了,报no such constructor错误,但是,这个微服务在发布到环境上的时候在本地 Idea 里面启动过,但是在 Idea 里面启动缺没有任何报错。如下图所示:

问题复现

使用下面的 pom 文件引入依赖包,然后将项目打包项目为 jar 包启动就可以复现问题,配置如下:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.18.RELEASE</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>2.3.2</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

但是直接在 Idea 里面启动项目,则可以看到是可以正常启动的。如下图所示:

问题原因

启动报错原因

从上面报错的堆栈信息可以看到是在AbstractDialect的 57 行报的错,但是查看这行代码,实际上就是通过 lambda 表达式创建了一个DefaultCountSqlParser对象,代码如下:

同时查看DefaultCountSqlParser的源码发现,它本身也没有定义任何有参数的构造函数,那它应该是默认有无参构造函数的,那为啥会报no such constructor错误呢?问题定位到这里有点定位不下去了。代码如下:

后来又再次去看了报错的堆栈日志,发现在它的下面还有Caused by: java.lang.VerifyError: Bad return type报错。如下图所示:

然后拿着这个报错去问了下 AI,AI 的回答:可能是 jar 包编译时的版本和运行时的版本不一致,且涉及到了方法签名的变更。如下图所示:

同时查看上面报错的堆栈信息提到了DefaultCountSqlParsersqlToCount()方法,原因是:net/sf/jsqlparser/statement/select/PlainSelect is not assignable to net/sf/jsqlparser/statement/select/Select

然后查看这个方法,发现它方法的返回值声明类型是net/sf/jsqlparser/statement/select/Select,方法内部返回的是net/sf/jsqlparser/statement/select/PlainSelect类型。如下图所示:

查看net/sf/jsqlparser/statement/select/PlainSelect确实和net/sf/jsqlparser/statement/select/Select没有继承关系,同时发现当前实际引入的jsqlparser的版本是 1.1 的版本。然后去 maven 搜索这个 jar 包,发现pagehelper-spring-boot-starter实际想要引入的jsqlparser版本是 4.7 的版本,但是因为引入了mybatis-plus的 2.3.3 版本,它引入了jsqlparser的版本是 1.1,同时因为它和pagehelper-spring-boot-starter依赖jsqlparser的路径长度相同,且它在 pom 文件声明的前面。按照 maven 依赖调节的原则:路径长度相同时会取声明在前的,因此引入了jsqlparser的 1.1 版本。如下图所示:

从类加载的过程分析上面的报错:通过new DefaultCountSqlParser属于对一个类型的主动引用,会触发类加载,类加载又分为:加载、验证、准备、解析、初始化。

根据《深入理解JVM虚拟机》书中解释:在验证过程中会对方法的字节码进行验证。如下图所示:

对于本案例中,在验证的过程中,JVM 发现sqlToCount()方法声明返回net/sf/jsqlparser/statement/select/Select,同时方法体中返回的是net/sf/jsqlparser/statement/select/PlainSelect类型,这就要求它们有继承关系,但是因为当前引入的是jsqlparser的版本是 1.1 版本,在这个 jar 包它们两个并不具备父子关系,因此校验失败了。

Idea 启动不报错原因

那为啥打包成 jar 包启动就会报错,但是在 Idea 中启动就不报错呢?最开始我以为是 Idea 自动引入了新版本的 jar 包,但是我把 Idea 的启动命令拷贝出来,搜索classpath中设置的jsqlparser版本,发现它引入的也是 1.1 版本,到这里感觉怎么都解释不通了呀!如下图所示:

后面又回去翻了翻书,发现书上说有个-Xverify:none参数可以关闭校验,巧了的是上面启动命令图中的第一行的最后恰好就是这个参数(-noverify 实际上就是 -Xverify:none 的一个快捷别名)。

真相终于大白了,Idea 默认应该是把类加载的验证这个操作给关闭了,因此通过 Idea 启动的时候不会进行校验,自然也不会报错了。

那如何让 Idea 启用校验呢?在 Idea 的 Run/Debug Configurations 这里把 Disable launch optimization 这个配置相勾选上,然后启动项目,在控制台就可以看到一模一样的报错了。如下图所示:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/27 2:25:31

地下管网的“水质哨兵”如何实现72小时隐患预警?

地下管网水质监测系统是集感知、传输、处理、应用于一体的智能化在线监测体系&#xff0c;可实时采集管网关键节点水质数据&#xff0c;实现异常预警、污染溯源与运维优化&#xff0c;适配地下潮湿、腐蚀、信号弱等复杂环境&#xff0c;广泛用于市政排水、工业园区排污、黑臭水…

作者头像 李华
网站建设 2026/3/15 2:43:11

Spring Boot 核心接口与扩展点详细指南

Spring Boot 核心接口与扩展点详细指南引言在Spring Boot的便捷背后&#xff0c;隐藏着一套精妙而强大的扩展机制。无论是容器启动的瞬间&#xff0c;还是Bean生命的各个阶段&#xff0c;亦或是Web请求的完整链路&#xff0c;框架都为我们预留了丰富的扩展接口。这些接口如同Sp…

作者头像 李华
网站建设 2026/3/31 4:04:00

ModbusRTC学习

1. ModbusRTU介绍 ModbusRTC本身只定义了数据报文的结构&#xff0c;底层物理链接依赖与串行通信标准。主从通信模式&#xff0c;一个主站设备发起请求&#xff0c;一个或多个从站设备响应请求全双工 异步通信 2. 物理层 - modbusRTU的载体 2.1 RS485 RS-485 是 Modbus RT…

作者头像 李华
网站建设 2026/3/30 0:36:34

2023A卷,递增字符串

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:华为OD面试 文章目录 一、🍀前言 1.1 ☘️题目详情 1.2 ☘️参考解题答案 一、🍀前言 2023A卷,递增字符串。 1.1 ☘️题目详情 题目: 定义字符串…

作者头像 李华
网站建设 2026/3/29 12:18:00

考虑晶圆尺寸与负载,如何选择合适的HIWIN晶圆搬运机械手?

在半导体、LED等精密制造领域&#xff0c;晶圆搬运机械手的选型往往直接影响产线效率和产品良率。尤其是当涉及不同尺寸的晶圆和多样的负载需求时&#xff0c;选对机型就像给设备配了“合身的骨骼”&#xff0c;既不能“小马拉大车”&#xff0c;也不能“大材小用”。作为深耕行…

作者头像 李华
网站建设 2026/3/28 23:44:12

武汉光缆牵引机厂家

在华中地区&#xff0c;武汉作为重要的通信枢纽与交通中心&#xff0c;汇聚了众多网络基建工程项目。选择一家可靠的本地或服务本地的光缆牵引机厂家&#xff0c;意味着能获得更迅捷的响应、更贴合区域施工特点的技术支持&#xff0c;这对于保障项目工期与质量至关重要。 一家靠…

作者头像 李华