Tomcat启动报错:ClassFormatException: Invalid byte tag in constant pool: 19

一. 遇到问题❓

❗️先放一张tomcat启动时报错的日志❗️

image-20200820230551978

我所用的JDK版本为:jdk8

tomcat版本为:tomcat 7.xx

从字面以后可以看到 Unable to process Jar entry xxx for annotations (无法处理注释的xx Jar包的条目)

对应的报错是**ClassFormatException **( 类格式异常)

这个异常继承了RuntimeException(运行时异常)

官方解释如下:

Thrown when the BCEL attempts to read a class file and determines that the file is malformed or otherwise cannot be interpreted as a class file (当BCEL试图读取类文件并确定该文件格式不正确或不能将其解释为类文件时抛出)

1.1 名词解释🔍

  • 这里的BCEL为”Byte Code Engineering Library“的缩写 是java字节码操作库,它是Apache Software Foundation 的 Jakarta 项目的一部分,是Java classworking 最广泛使用的一种框架,可以让你深入JVM汇编语言进行类操作的细节 tomcat中实现了bcel的功能

  • lib/tomcat-coyote.jar中的包com.apache.tomcat.util.bcel为相关类

抛出上面异常【Invalid byte tag in constant pool: 19】的原因:

at org.apache.tomcat.util.bcel.classfile.Constant.readConstant(Constant.java:97)
at org.apache.tomcat.util.bcel.classfile.ConstantPool.(ConstantPool.java:55)

读取常量池时在Constant.readConstant方法中用switch-case对读取到的首字节进行判断(这个字节标识了常量属于哪种类型),如果无法匹配则抛出异常

(附上一一篇关于java字节码的文章 https://blog.csdn.net/umasanhao/article/details/47338623)

下面为反编译的结果,异常的抛出的值为19,在case的情况里并没有定义,所以抛出了异常

{
    byte b = file.readByte(); // Read tag byte

    switch(b) {
    case Constants.CONSTANT_Class:              return new ConstantClass(file);
    case Constants.CONSTANT_Fieldref:           return new ConstantFieldref(file);
    case Constants.CONSTANT_Methodref:          return new ConstantMethodref(file);
    case Constants.CONSTANT_InterfaceMethodref: return new
                                        ConstantInterfaceMethodref(file);
    case Constants.CONSTANT_String:             return new ConstantString(file);
    case Constants.CONSTANT_Integer:            return new ConstantInteger(file);
    case Constants.CONSTANT_Float:              return new ConstantFloat(file);
    case Constants.CONSTANT_Long:               return new ConstantLong(file);
    case Constants.CONSTANT_Double:             return new ConstantDouble(file);
    case Constants.CONSTANT_NameAndType:        return new ConstantNameAndType(file);
    case Constants.CONSTANT_Utf8:               return new ConstantUtf8(file);
    default:
      throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
    }
  }
image-20200820234255738

二. 问题解决🔧

问题来了——这个【19】到底是个什么情况呢?

JDK9中新增了一个很重要的特性——模块化,使用JDK9创建模块并打包后会有一个module-info.class的类 其中常量结构可能有19-CONTANT_Module and 20-CONSTANT_Package两种,不在原有的11种取值之内(如上图所示)

Apache对此也有相关的bug报告 大家可以移步下方地址观看

https://bz.apache.org/bugzilla/show_bug.cgi?id=60688
并最后在如下版本做了修复
- trunk for 9.0.0.M18 onwards
- 8.5.x for 8.5.12 onwards
- 8.0.x for 8.0.42 onwards
- 7.0.x for 7.0.76 onwards

2.1 解决方案:

  1. 若没有用到该jar包,可以剔除

  2. 换一个tomcat版本

  3. 通过修改tomcat加载的配置,不对相应的jar包进行扫描

    https://blog.csdn.net/JackRen_Developer/article/details/82288488
    tomcat.util.scan.StandardJarScanFilter.jarsToSkip

  4. jetty也有类似的温柔,jetty新版本解决了加扫描module-info.class的问题,忽略了这个类

    https://blog.csdn.net/baidu_34036884/article/details/80151963

三. Reference

1.https://blog.csdn.net/kinder10314/article/details/86629992
2.https://blog.csdn.net/umasanhao/article/details/47338623
3.http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/util/bcel/classfile/ClassFormatException.html
4.https://bz.apache.org/bugzilla/show_bug.cgi?id=60688

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值