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

提供给其他系统使用的jar包造成tomcat启动报错:
Unable to process Jar entry [module-info.class] from Jar [jar:file:/xxxxxxxx/lombok-1.18.4.jar!/] for annotations
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19

问题信息搜集:
    有人给lombok提了bug(https://github.com/rzwitserloot/lombok/issues/1801) tomcat8.0环境启动读取module-info.class报错
    然后一个作者回复:我们加了java9的module-info是有原因的, 应该换tomcat版本或者给tomcat提bug兼容这个 大概意思是这样
    
    进行了一些信息搜集之后得出:从lombok-1.16.20开始打包中存在一个叫module-info.class的文件,一些版本的tomcat启动时,如果classpath下有这个包就会报上面的错误
    
尝试的解决方案:
    1.maven中将lombok的scope设为provider;——有效,lombok为注解增强编译,运行时不需要
    2.对方系统tomcat版本为7.0.61,本地换用tomcat 8.0.53;——有效,未发现异常
    
问题相关知识梳理:

    bcel - [Byte Code Engineering Library] apache旗下的字节码处理框架
    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.<init>(ConstantPool.java:54)
 
    读取常量池时在Constant.readConstant方法中用switch-case对读到的首字节进行判断(这个字节标识了常量属于哪种类型),如果无法匹配则抛出异常,
    (JAVA字节码 https://blog.csdn.net/umasanhao/article/details/47338623
    下面为反编译结果,异常抛出的值为19,在case的情况里没有定义所以抛出异常

static Constant readConstant(DataInputStream file) throws IOException, ClassFormatException {
        byte b = file.readByte();
        switch(b) {
        case 1:
            return ConstantUtf8.getInstance(file);
        case 2:
        case 13:
        case 14:
        case 17:
        default:
            throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
        case 3:
            return new ConstantInteger(file);
        case 4:
            return new ConstantFloat(file);
        case 5:
            return new ConstantLong(file);
        case 6:
            return new ConstantDouble(file);
        case 7:
            return new ConstantClass(file);
        case 8:
            return new ConstantString(file);
        case 9:
            return new ConstantFieldref(file);
        case 10:
            return new ConstantMethodref(file);
        case 11:
            return new ConstantInterfaceMethodref(file);
        case 12:
            return new ConstantNameAndType(file);
        case 15:
            return new ConstantMethodHandle(file);
        case 16:
            return new ConstantMethodType(file);
        case 18:
            return new ConstantInvokeDynamic(file);
        }
    }

 
  那么19是个啥情况呢?
  JDK9新增了一个特别重要的特性——模块化,使用JDK9创建模块打包后有一个module-info.class的类
  其中常量结构可能有19 - CONSTANT_Module and  20 - CONSTANT_Package两种,不在原有的11种取值之内  
 
  以下为相关的tomcat的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
 
  比较org.apache.tomcat.util.bcel.classfile.Constant.readConstant的代码确认,我正在使用的tomcat版本 7.0.61(未修复)和8.0.53(已修复)
  修复部分的代码如下:

case 16:
case 19:
case 20:
    skipSize = 2;
    break;
case 9:

其他相关:

    另外一种解决方案,通过修改tomcat加载的配置,不对相应的jar进行扫描
    https://blog.csdn.net/JackRen_Developer/article/details/82288488
    tomcat.util.scan.StandardJarScanFilter.jarsToSkip

    jetty也有类似的问题,jetty新版本解决了加扫描module-info.class的问题,忽略了这个类
    https://blog.csdn.net/baidu_34036884/article/details/80151963

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值