首页 > 其他分享 >easyexcel和poi版本冲突报错深入解析v2

easyexcel和poi版本冲突报错深入解析v2

时间:2024-06-18 14:58:06浏览次数:26  
标签:cn MyGet zxh easyexcel v2 报错 poi

easyexcel报错解决

问题

项目由poi改用easyexcel,报错如下: java.lang.NoSuchMethodError: ‘org.apache.poi.ss.usermodel.CellType
org.apache.poi.ss.usermodel.Cell.getCellType()’

原因

easyexcel中的poi和项目原本的poi版本冲突问题。 由于之前做过easyexcel项目,就把所以子工程pom里的poi注释掉了。
关键:忽略了parent项目pom的dependencyManagement中版本锁定的poi,这里误以为在子工程未使用就不会冲突。

解决

将项目所有有关poi的dependency全部注释掉,包括dependencies和dependencyManagement。
推荐:使用快捷键ctrl+shift+f直接搜索poi,找到直接注释

上述只是问题的解决方案,并没有系统的介绍为什么会报错。

1.问题

1、报的什么错?NoSuchMethodError 方法不存在错误
2、发生在编译期,还是运行时?
3、如果发生在运行时,为什么编译的时候没有识别出来这个方法不存在?

那么通过下面的解析,会清楚的理解上述问题。

2.模拟错误

由于easyexcel源码不方便修改,所以这里使用自己代码实现(代码无实际意义),主要演示报错。

2.1创建2个maven项目

easye模拟easyexcel,poi模拟poi。
在这里插入图片描述
自己项目调用了easyexcel的方法,而easyexcel又调用了poi方法。所以模拟,需要在poi创建一个getType方法。easye里创建testGet方法调用getType方法。

具体代码如下:
poi的pom:初始版本设置为1.0,版本后面会更改

<?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>cn.zxh</groupId>
        <artifactId>test01</artifactId>
        <version>1.0</version>
    </parent>

    <groupId>cn.zxh</groupId>
    <artifactId>poi</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

CellImpl.java

package cn.zxh.poi;

public class CellImpl implements Cell {
    @Override
    public int getType() {
        return 1;
    }
}

Cell.java

package cn.zxh.poi;

public interface Cell {
    public int getType();
}

easye的pom:初始版本设置为1.0,引用poi1.0版本库

<?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>cn.zxh</groupId>
        <artifactId>test01</artifactId>
        <version>1.0</version>
    </parent>
    <groupId>cn.zxh</groupId>
    <artifactId>easye</artifactId>
    <version>1.0</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>cn.zxh</groupId>
            <artifactId>poi</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

</project>

MyGet.java

package cn.zxh.easye;

import cn.zxh.poi.Cell;
import cn.zxh.poi.CellImpl;
import java.util.Objects;

public class MyGet {
    public void testGet(){
        Cell cell = new CellImpl();
        //没有实际意义,主要是调用getType
        if(Objects.equals(cell.getType(),1)){
            System.out.println("pass");
        }
        System.out.println("fail");
    }
}

2.2安装到本地maven仓库

点击安装
在这里插入图片描述
然后找到自己的maven仓库内容如下
在这里插入图片描述

在这里插入图片描述

2.3在其他项目引入easye库

注:找个别的工程(不要还在这个工程),因为模拟引入easyexcel。自己工程肯定和easyexcel不在一个工程下。
在这里插入图片描述

2.4创建测试类并模拟调用

这里直接调用MyGet 的testGet。

package com.zxh.project.test1;

import cn.zxh.easye.MyGet;
import cn.zxh.poi.Cell;

public class MyTest {
    public static void main(String[] args) {
        MyGet myGet = new MyGet();
        myGet.testGet();
    }
}

这里先模拟版本一致正常情况,发现正常运行。
在这里插入图片描述

2.5降低poi的版本

找到之前自己的poi项目,更改getType,这里把返回类型换成String。
在这里插入图片描述
在这里插入图片描述

poi.pom里的版本改为0.5,然后只打包poi
在这里插入图片描述

在这里插入图片描述

2.6使用降低poi0.5版本

其他项目pom引入0.5版本
在这里插入图片描述
这里运行时会使用0.5,这就是常见的poi和easyexcel版本的冲突。
在这里插入图片描述

2.6错误模拟成功

果然不出所料,运行时报错了,这里打了断点,编译肯定通过的,确实为运行时报错。
在这里插入图片描述
在这里插入图片描述

2.7再再降低poi版本

重复上部分,降低到0.1,直接把poi中的getType的方法删掉(方便理解),再打包,然后引入改为0.1

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
发现依然编译通过,运行时报错。

3.原因分析

那么有疑问,既然用的是低版本poi0.1库,这个方法都不存在,为什么还编译通过了呢。那么再做个实验。

首先将easye1.0 和MyTest复制到另一个普通java项目。

在这里插入图片描述
在这里插入图片描述
然后添加类库
在这里插入图片描述

然后这里也是运行时报错,只是错误变了,类不存在。因为压根就没有引入poi的库,只引入了easye,poi库中的类肯定不存在
在这里插入图片描述
然后这里引入的easye库(包括maven引入的),都是已经编译好的.class文件
在这里插入图片描述

4.总结

那么我们就可以大胆的猜测了(为什么时猜测,我也不知道对不对,欢迎大家讨论)
编译阶段,仅仅对直接引入的库中的方法进行检测是否存在,例如这里只判断easye库的MyGet.testGet,而easye库如果引用了其他库的方法,例如poi中的方法,由于已经编译成了MyGet.class,不再进行MyGet.class重新编译,所以深层的方法不在编译器发现(因为编译MyTest.class,只需要知道MyGet.testGet即可)。

JVM运行时,会根据方法的签名进行调用,如果方法的签名不在,报错。
下面为MyGet.testGet的class源码,
其中invokeinterface #4 <cn/zxh/poi/Cell.getType : ()I> count 1
这里就是获取cn/zxh/poi/Cell.getType : ()I 这种签名的方法。如果没有报错。

2.6错误模拟成功

这里报错是getType已经改成了String类型,I标识int,签名不一致找不到。

2.7再再降低poi版本

这里报错更简单,直接方法都删掉了,签名肯定找不到。

3.原因分析

这个里面的报错,是根据下面的源码
0 new #2 <cn/zxh/poi/CellImpl>
根据类路径找不到类,库都没有引入,所以报错。

 0 new #2 <cn/zxh/poi/CellImpl>
 3 dup
 4 invokespecial #3 <cn/zxh/poi/CellImpl.<init> : ()V>
 7 astore_1
 8 aload_1
 9 invokeinterface #4 <cn/zxh/poi/Cell.getType : ()I> count 1
14 invokestatic #5 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
17 iconst_1
18 invokestatic #5 <java/lang/Integer.valueOf : (I)Ljava/lang/Integer;>
21 invokestatic #6 <java/util/Objects.equals : (Ljava/lang/Object;Ljava/lang/Object;)Z>
24 ifeq 35 (+11)
27 getstatic #7 <java/lang/System.out : Ljava/io/PrintStream;>
30 ldc #8 <pass>
32 invokevirtual #9 <java/io/PrintStream.println : (Ljava/lang/String;)V>
35 getstatic #7 <java/lang/System.out : Ljava/io/PrintStream;>
38 ldc #10 <fail>
40 invokevirtual #9 <java/io/PrintStream.println : (Ljava/lang/String;)V>
43 return

标签:cn,MyGet,zxh,easyexcel,v2,报错,poi
From: https://blog.csdn.net/qq_38367575/article/details/139770484

相关文章

  • mysql数据库名带下划线等特殊字符时,分权限报错
    原文链接:mysql数据库名带下划线分权限报错_mob64ca12f24f3a的技术博客_51CTO博客 MySQL数据库名带下划线分权限报错解析在使用MySQL进行数据库操作时,我们经常会遇到数据库名带下划线导致权限报错的情况。这是因为MySQL对于数据库名中的下划线有特殊的处理机制,容易导致权限控制......
  • 界面控件DevExpress v24.1全新发布 - 跨平台性进一步增强
    DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress今年第一个重要版本v23.1正式发布,该版本拥有众多新产品和数十个具有高影响力......
  • 植物大战僵尸杂交版最新pvzHE_v2.1.0含游戏窗口放大工具
    植物大战僵尸杂交版是由B站”潜艇伟伟迷”UP主制作的一款同人策略塔防游戏,也叫pvzHE,该游戏由《植物大战僵尸》原版魔改而来,引入了创新的杂交合成系统,让玩家可以将不同植物进行杂交,创造出具有全新能力和外观的植物,拥有众多不同种类的植物和角色,每个角色都有独特的技能。2.1.0......
  • 关于Visual Studio报错scanf_s等*_s代码报错的解决方案
    问题:用visualstudio写代码时经常碰到scanf报错,strcpy报错等情况但是又不想改代码怎么办呢?解决办法点击"项目"点击"属性""C/C++""常规""SDL检查"设置为否然后确定即可正常编译......
  • 云原生周刊:Harbor v2.11 版本发布 | 2024.6.17
    开源项目推荐DeschedulerDescheduler是一个工具,可用于优化Kubernetes集群中Pod的部署位置。它可以找到可以移动的Pod,并将其驱逐,让默认调度器将它们重新调度到更合适的节点上。ProwlerProwler是一款适用于AWS、Azure、GCP和Kubernetes的开源安全工具,用于进行安全评......
  • 快速解决:使用Mindspore框架时报错!!libgomp-6e1a1d1b.so.1.0.0: cannot allocate memory
    前言:最近在用ms跑大模型,需要做好多步骤,遇到报错跟大家一起分析一下吧刚开始转换权重就遇到了下述报错:ImportError:/root/anaconda3/envs/MS/lib/python3.9/site-packages/torch/lib/../../torch.libs/libgomp-6e1a1d1b.so.1.0.0:cannotallocatememoryinstaticTLSblo......
  • Syncaila for Mac(多机位自动对视频音频同步工具)v2.1.4版
    Syncailamac版是Macos上一款多机位自动对视频音频同步工具,可以对来自多个摄像机和录像机的视频和音频片段进行全自动同步,Syncailamac下载非常适合经常做多机位拍摄和视频剪辑的朋友,帮助你节省大量时间和精力,以最大程度地专注于创意编辑任务!SyncailaforMac(多机位自动对视......
  • 报表开发工具DevExpress Reporting v23.2 - 增强PDF导出、多平台打印等
    DevExpressReporting是.NETFramework下功能完善的报表平台,它附带了易于使用的VisualStudio报表设计器和丰富的报表控件集,包括数据透视表、图表,因此您可以构建无与伦比、信息清晰的报表。DevExpressReporting控件日前正式发布了v23.2,新版本增强了PDF导出、macOS、Linux平台打......
  • Docker系列 V2 - Docker安装jdk8
    安装的两种方式通过已有的镜像直接pull安装;自己通过dockerfile等命令打包一个镜像安装(此种方式我们到已有镜像满足不了自身需求时使用);本章是根据第一种方式安装的【1.1】安装镜像根据文章docker安装指定版本的tag镜像得到安装JDK的Docker命令dockerpullprimetoninc/j......
  • 解决Vscode报错 This may occur if... 问题
    今天在用Vscode写代码时,一直出现报错Thismayoccurif...,我一直在找路劲问题,但是发现自己的路径没有问题。执行task.josn时可以生成相应的.exe文件,就是在按下F5时,launch.json文件一直报这个错误,我再运行昨天写的代码,也不可以运行了,也是出现这个问题。之后经过不断查找和尝试,终于......