Android Gradle Plugin处理module-info.class报错

背景

项目接入Kotlin之后,在进行打包时,多个 Gradle Plugin 处理class时抛出异常,包括使用asm或者javassist库都会报错,

具体异常信息如下:
asm:

Caused by: java.lang.RuntimeException
	at org.objectweb.asm.ClassVisitor.visitModule(ClassVisitor.java:148)
	at org.objectweb.asm.ClassReader.readModule(ClassReader.java:731)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:632)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:500)
复制代码

javassist:

java.io.IOException: invalid constant type: 19 at 5
	at javassist.bytecode.ConstPool.readOne(ConstPool.java:1244)
	at javassist.bytecode.ConstPool.read(ConstPool.java:1175)
	at javassist.bytecode.ConstPool.<init>(ConstPool.java:185)
	at javassist.bytecode.ClassFile.read(ClassFile.java:829)
	at javassist.bytecode.ClassFile.<init>(ClassFile.java:154)
	at javassist.CtClassType.<init>(CtClassType.java:96)
	at javassist.ClassPool.makeClass(ClassPool.java:729)
	at javassist.ClassPool.makeClass(ClassPool.java:707)
	at javassist.ClassPool$makeClass$2.call(Unknown Source)
复制代码

问题原因

经排查,插件报错的时机是在处理module-info.class,那么这个文件是做什么的呢?

module-info.class

首先,我们发现这个module-info.class存在于多个kotlin官方库中,例如:

org.jetbrains.kotlin:kotlin-stdlib-common:1.4.21
+--- kotlin-stdlib-jdk8-1.4.21.jar
     +--- META-INF
          +--- versions
               +--- 9
                    +--- module-info.class
复制代码

module-info.class 内容如下:

module kotlin.stdlib {
    exports kotlin;
    exports kotlin.annotation;
    exports kotlin.collections;
    exports kotlin.collections.unsigned;
    exports kotlin.comparisons;
    ...
}
复制代码

baidu + google,找到这个class的作用;
简单来讲,就是JDK9支持模块化,类似Dart语言的包组织,JS的export,这样可以管理或者重新组织一个新的包,而不是像JDK8以下一样,只能通过Java修饰符来控制访问权限;而这个module-info.class就是来管理和描述这个包的;

在JDK8及以下,module-info.class并不会起作用,只有在JDK9以上才会起作用;

可以看到这个class并不是一个正常的class,并不包含类或者方法,所以asm和javassist处理这个class时,就会解析报错;

解决办法

方法一:在处理class时,判断class是否为module-info.class签名,如果是,则跳过;但是需要所有的插件都做了这样的处理;

方法二:编写独立的插件,专门用来删除module-info.class,并且第一个注册这个transform,这样后面所有的插件都不会处理到这个class;缺点是,项目就不能支持JDK9了,但是Android目前相关库最高支持到JDK8,所以影响不大;

最终我们项目采用的方法二,目前运行稳定,未发现异常;

分类:
Android
标签: