jedis java.lang.verifyerror_jedis:exception is java.lang.VerifyError: Bad type on operand stack

本文记录了一次在项目中遇到的关于Jedis与Spring Data Redis的兼容性问题,通过调整Jedis版本成功解决了异常错误。

项目中需要用到缓存,经过比较后,选择了redis,客户端使用jedis连接,也使用到了spring提供的spring-data-redis。配置正确后启动tomcat,发现如下异常:

=============================================================================

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisTemplate' defined in class path resource [spring.xml]: Initialization of bean failed; nested exception is java.lang.VerifyError: Bad type on operand stack

Exception Details:

Location:

org/springframework/data/redis/connection/jedis/JedisConnectionFactory.afterPropertiesSet()V @109: invokespecial

Reason:

Type 'redis/clients/jedis/JedisPoolConfig' (current frame, stack[3]) is not assignable to 'org/apache/commons/pool2/impl/GenericObjectPoolConfig'

Current Frame:

bci: @109

flags: { }

locals: { 'org/springframework/data/redis/connection/jedis/JedisConnectionFactory' }

stack: { 'org/springframework/data/redis/connection/jedis/JedisConnectionFactory', uninitialized 73, uninitialized 73, 'redis/clients/jedis/JedisPoolConfig', 'java/lang/String', integer, integer, 'java/lang/String' }

Bytecode:

0000000: 2ab4 000d c700 3d2a bb00 1759 2ab4 0003

0000010: 2ab4 0004 b700 18b5 000d 2ab4 0019 b800

0000020: 1a99 000e 2ab4 000d 2ab4 0019 b600 1b2a

0000030: b400 059e 000e 2ab4 000d 2ab4 0005 b600

0000040: 1c2a b400 0699 002e 2abb 001d 592a b400

0000050: 0a2a b400 0db6 001e 2ab4 000d b600 1f2a

0000060: b400 0db6 0020 2ab4 000d b600 21b7 0022

0000070: b500 07b1

Stackmap Table:

same_frame(@47)

same_frame(@65)

same_frame(@115)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)

at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:442)

at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)

at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550)

at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)

at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)

at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)

... 39 more

Caused by: java.lang.VerifyError: Bad type on operand stack

Exception Details:

Location:

org/springframework/data/redis/connection/jedis/JedisConnectionFactory.afterPropertiesSet()V @109: invokespecial

Reason:

Type 'redis/clients/jedis/JedisPoolConfig' (current frame, stack[3]) is not assignable to 'org/apache/commons/pool2/impl/GenericObjectPoolConfig'

Current Frame:

bci: @109

flags: { }

locals: { 'org/springframework/data/redis/connection/jedis/JedisConnectionFactory' }

stack: { 'org/springframework/data/redis/connection/jedis/JedisConnectionFactory', uninitialized 73, uninitialized 73, 'redis/clients/jedis/JedisPoolConfig', 'java/lang/String', integer, integer, 'java/lang/String' }

Bytecode:

0000000: 2ab4 000d c700 3d2a bb00 1759 2ab4 0003

0000010: 2ab4 0004 b700 18b5 000d 2ab4 0019 b800

0000020: 1a99 000e 2ab4 000d 2ab4 0019 b600 1b2a

0000030: b400 059e 000e 2ab4 000d 2ab4 0005 b600

0000040: 1c2a b400 0699 002e 2abb 001d 592a b400

0000050: 0a2a b400 0db6 001e 2ab4 000d b600 1f2a

0000060: b400 0db6 0020 2ab4 000d b600 21b7 0022

0000070: b500 07b1

Stackmap Table:

same_frame(@47)

same_frame(@65)

same_frame(@115)

at java.lang.Class.getDeclaredConstructors0(Native Method)

at java.lang.Class.privateGetDeclaredConstructors(Class.java:2493)

at java.lang.Class.getDeclaredConstructors(Class.java:1901)

at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:230)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:972)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:945)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)

at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)

at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)

at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)

at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)

at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1387)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1128)

at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)

... 50 more

===============================================================================

非常奇怪,由于google的访问限制,百度了半天也没什么结果,我就知道google一定可以的,果断FQ搜索,果然没有让我失望,

google结果链接:http://stackoverflow.com/questions/22704518/jedispoolconfig-is-not-assignable-to-genericobjectpoolconfig

看情况应该是jar包版本问题,我目前的版本为:jedis-2.1.0.jar + spring-data-redis-1.3.0.RELEASE.jar。

按照提示我将jedis升级成了jedis-2.4.2.jar。

再次运行,成功!!

<think>我们正在处理一个`java.lang.VerifyError: Bad return type`错误。根据引用[1],这个错误是由于JVM在加载类时进行字节码验证失败,通常是因为类文件不合法。具体来说,这个错误消息“Bad return type”表明方法返回的类型与声明不匹配。 根据引用[2]和[3],我们看到这个错误可能与RedisJedis)相关,特别是当创建`RedisTemplate`时。但同样的问题可能发生在其他库中,例如Kafka或者任何其他依赖库。 引用[4]提供了一个解决类似问题的思路:通过排除冲突的依赖版本或者降低依赖版本来解决。 ### 问题分析 1. **根本原因**:JVM字节码验证失败,通常是由于依赖库版本冲突导致。不同的依赖库可能引入了同一个库的不同版本,而这两个版本之间可能存在不兼容的字节码改动。 2. **常见场景**: - 项目依赖了同一个库的多个版本,而JVM加载了不兼容的版本。 - 编译时使用的库版本与运行时加载的库版本不一致。 ### 解决方案 #### ✅ 方案1: 检查并统一依赖版本(推荐) 使用Maven的依赖树分析工具,检查冲突的依赖并统一版本。 步骤: 1. 在项目根目录执行: ```bash mvn dependency:tree ``` 2. 查找包含`VerifyError`的类所在的库(例如,错误中提到的类可能是`redis.clients.jedis.JedisPoolConfig`,那么就查找`jedis`库的多个版本)。 3. 在`pom.xml`中通过`<dependencyManagement>`或直接排除冲突版本。 示例:统一Jedis版本 ```xml <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.0</version> <!-- 选择一个稳定版本 --> </dependency> ``` #### ✅ 方案2: 排除冲突的依赖 如果发现某个依赖引入了冲突的版本,排除它。 示例:排除旧版本的jsqlparser(如引用[4]所述) ```xml <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>2.0.0</version> <exclusions> <exclusion> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> </exclusion> </exclusions> </dependency> ``` #### ✅ 方案3: 清理Maven仓库并重新编译 有时本地Maven仓库中的损坏jar包会导致此问题: 1. 删除本地仓库中相关的依赖目录(例如`~/.m2/repository/redis/clients/jedis`)。 2. 重新执行`mvn clean install -U`(`-U`选项强制更新快照)。 ### 验证步骤 1. 在修复后,重新运行`mvn dependency:tree`确保没有冲突。 2. 重新启动应用,观察错误是否消失。 ### 根本原因说明 该错误是JVM字节码验证失败的表现,数学本质是方法签名的类型系统不一致: 设方法声明为: $$T \quad methodName(P_1, P_2, \dots, P_n)$$ 而实际返回的类型为$S$,则验证失败的条件为: $$S \not\subseteq T \quad \text{(即$S$不是$T$的子类型)}$$ 在字节码级别,JVM会严格检查返回类型的一致性[^1]。 §§相关问题§§ 1. 如何解读Maven依赖树? 2. JVM字节码验证机制详解? 3. 如何定位Java字节码冲突的具体类? [^1]: 引用[1]指出该错误由JVM类加载验证阶段引发 [^2]: 引用[2][3]展示了Jedis库引发的相同错误模式 [^4]: 引用[4]提供了通过版本管理解决的实际案例 </think>### 解决 `java.lang.VerifyError: Bad return type` 报错的方法 `java.lang.VerifyError: Bad return type` 错误是 JVM 字节码验证失败的典型表现,通常由依赖版本冲突或编译环境问题引起。以下是系统解决方案: --- #### ✅ 方案 1:统一依赖版本(推荐) 在 `pom.xml` 中显式声明冲突库的兼容版本: ```xml <dependencyManagement> <dependencies> <!-- 以 Jedis 和 JSQLParser 为例 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.3.1</version> <!-- 统一使用此版本 --> </dependency> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>4.5</version> <!-- 确保所有模块使用相同版本 --> </dependency> </dependencies> </dependencyManagement> <!-- 在具体依赖中排除冲突版本 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>2.0.0</version> <exclusions> <exclusion> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> </exclusion> </exclusions> </dependency> ``` --- #### ✅ 方案 2:强制依赖版本覆盖 在 `pom.xml` 中使用 `<dependency>` 覆盖传递依赖: ```xml <dependencies> <!-- 强制指定 jsqlparser 版本 --> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>4.5</version> </dependency> <!-- 其他依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> </dependencies> ``` --- #### ✅ 方案 3:清理并重建编译环境 1. **清理 Maven 本地仓库**: ```bash mvn dependency:purge-local-repository rm -rf ~/.m2/repository/com/github/jsqlparser # 删除冲突库的缓存 ``` 2. **重新编译并检查依赖树**: ```bash mvn clean install -U mvn dependency:tree -Dincludes=com.github.jsqlparser ``` 输出应显示**唯一版本**: ``` [INFO] \- com.github.jsqlparser:jsqlparser:jar:4.5:compile ``` --- ### 错误机制分析 该错误本质是 JVM 字节码验证失败: $$ \text{VerifyError} = \begin{cases} \text{方法返回类型 } T_1 \\ \text{实际返回类型 } T_2 \\ T_1 \not\equiv T_2 \end{cases} $$ 当依赖库 $A$ 编译时使用 $Lib_v1$,而依赖库 $B$ 使用 $Lib_v2$ 时,若 $v1$ 和 $v2$ 的方法签名不兼容,JVM 验证器会检测到类型不一致引发此错误[^1]。 --- ### 验证步骤 1. **检查依赖冲突**: ```bash mvn dependency:tree | grep -E "jedis|jsqlparser" ``` 2. **运行时验证**: ```java public class VersionCheck { public static void main(String[] args) { System.out.println("Jedis版本: " + redis.clients.jedis.Jedis.class.getPackage().getImplementationVersion()); System.out.println("JSQLParser版本: " + net.sf.jsqlparser.JSQLParserException.class.getPackage().getImplementationVersion()); } } ``` 输出应显示**统一版本号** --- ### 根本解决方案 通过依赖管理消除版本冲突: $$ \forall \, \text{lib} \in \text{Dependencies}, \, \exists! \, v \in \text{Versions} $$ 即确保每个库在依赖树中**只存在唯一版本**[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值