Caused by: java.lang.IllegalStateException: Unsupported metadata version. Check that your Kotlin version is >= 1.0
at dagger.internal.codegen.kotlin.KotlinMetadata.metadataOf(KotlinMetadata.java:206)
at dagger.internal.codegen.kotlin.KotlinMetadata.from(KotlinMetadata.java:186)
at dagger.internal.codegen.kotlin.KotlinMetadataFactory.create(KotlinMetadataFactory.java:56)
at dagger.internal.codegen.kotlin.KotlinMetadataUtil.isCompanionObjectClass(KotlinMetadataUtil.java:100)
at dagger.internal.codegen.ModuleProcessingStep.process(ModuleProcessingStep.java:116)
at dagger.internal.codegen.ModuleProcessingStep.process(ModuleProcessingStep.java:59)
at dagger.internal.codegen.validation.TypeCheckingProcessingStep.lambda$process$0(TypeCheckingProcessingStep.java:51)
at com.google.common.collect.SingletonImmutableBiMap.forEach(SingletonImmutableBiMap.java:65)
at dagger.internal.codegen.validation.TypeCheckingProcessingStep.process(TypeCheckingProcessingStep.java:48)
at dagger.internal.codegen.ModuleProcessingStep.process(ModuleProcessingStep.java:104)
at dagger.internal.codegen.ModuleProcessingStep.process(ModuleProcessingStep.java:59)
at dagger.shaded.auto.common.BasicAnnotationProcessor$ProcessingStepAsStep.process(BasicAnnotationProcessor.java:495)
at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:228)
at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:208)
at org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor.process(incrementalProcessors.kt:90)
at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:166)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:980)
... 41 more
更新Dagger版到2.46即可解决该问题。
在开始分析前因后果之前,我们先对metadata做个简单了解。
任何经过Kotlin/JVM编译器编译生成的class文件,都会带有@Metadata注解,如下是一个.kt文件生成的字节码反编译后的java代码
@Module
@Metadata(
mv = {1, 9, 0},
k = 1,
d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0003\b\u0007\u0018\u0000 \u00032\u00020\u0001:\u0001\u0003B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0004"},
d2 = {"Lcom/example/doudindemo/AnimalsModule;", "", "()V", "Companion", "doudindemo_debug"}
)
public final class AnimalsModule {
}
Kotlin.Metadata类中解释了每个属性的作用:
mv :编译时的元数据版本, 一般和kotlin 插件版本走,比如我现在用的kotlin 1.9.22, mv就是{1,9,0}, 基本上就是mojor,minor
k :表明这个注解编码的元数据的种类,比如1是Class,2是File等, 超出范围的值就被当做非kotlin文件。
d1,d2 :根据k不同而不同
之所以这样简短命名,是为了减小生成的文件的大小。
那么生成的@Metadata有什么用呢?
字节码混淆器或者注解预处理器会用到,他们需要读取或修改metadata,为了简化样板代码和重复造轮子, kotlinx-metadata-jvm库就诞生了,提供了一套标准工具类。
现在我们回过头来看上面的错误,原因就是项目引用的Dagger库(2.26),它也使用了kotlinx-metadata-jvm库(0.1.0)来处理@Metadata注解,但是metadata库版本比较老,不支持当前编译环境生成的class文件中的Metadata,就好比我最多只支持java6, 你给我来个java 8, 我干不了。
那具体是怎么不支持呢?又是不支持哪个属性?
接下来需要看源码了,我们首先定位报错位置
Caused by: java.lang.IllegalStateException: Unsupported metadata version. Check that your Kotlin version is >= 1.0
at dagger.internal.codegen.kotlin.KotlinMetadata.metadataOf(KotlinMetadata.java:206)
KotlinClassMetadata metadata = KotlinClassMetadata.read(header);
if (metadata == null) {
// Should only happen on Kotlin < 1.0 (i.e. metadata version < 1.1)
throw new IllegalStateException(
"Unsupported metadata version. Check that your Kotlin version is >= 1.0");
}
这里就是编译报错的信息位置,由此可见,KotlinClassMetadata.read(header)返回了null, 接着看为什么返回null。
//kotlinx.metadata.jvm.KotlinClassMetadata.kt
companion object {
/**
* Reads and parses the given header of a Kotlin JVM class file and returns the correct type of [KotlinClassMetadata] encoded by
* this header, or `null` if this header encodes an unsupported kind of Kotlin classes or has an unsupported metadata version.
*
* Throws [InconsistentKotlinMetadataException] if the metadata has inconsistencies which signal that it may have been
* modified by a separate tool.
*
* @param header the header of a Kotlin JVM class file to be parsed
*/
@JvmStatic
fun read(header: KotlinClassHeader): KotlinClassMetadata? {
// We only support metadata of version 1.1.* (this is Kotlin from 1.0 until today)
if (!JvmMetadataVersion(
header.metadataVersion,
(header.extraInt and (1 shl 3)/* see JvmAnnotationNames.METADATA_STRICT_VERSION_SEMANTICS_FLAG */) != 0
).isCompatible()
) return null
return try {
when (header.kind) {
KotlinClassHeader.CLASS_KIND -> KotlinClassMetadata.Class(header)
KotlinClassHeader.FILE_FACADE_KIND -> KotlinClassMetadata.FileFacade(header)
KotlinClassHeader.SYNTHETIC_CLASS_KIND -> KotlinClassMetadata.SyntheticClass(header)
KotlinClassHeader.MULTI_FILE_CLASS_FACADE_KIND -> KotlinClassMetadata.MultiFileClassFacade(header)
KotlinClassHeader.MULTI_FILE_CLASS_PART_KIND -> KotlinClassMetadata.MultiFileClassPart(header)
else -> KotlinClassMetadata.Unknown(header)
}
} catch (e: InconsistentKotlinMetadataException) {
throw e
} catch (e: Throwable) {
throw InconsistentKotlinMetadataException("Exception occurred when reading Kotlin metadata", e)
}
}
}
这里会判断生成class的Metadata版本是否兼容, 不兼容返回null
if (!JvmMetadataVersion(
header.metadataVersion,
(header.extraInt and (1 shl 3)) != 0
).isCompatible()
) return null
是否兼容的要求(满足其中一条):
严格模式: 需要生成的Metadata的major==依赖的major(1), 生成的minor <= 依赖的minor(1)
非严格模式: 需要生成的Metadata中的major==1, minor<=4才算兼容
//kotlinx.metadata.internal.metadata.jvm.deserialization.JvmMetadataVersion.java
//依赖的metadata版本, major=1, minor=1
public static final JvmMetadataVersion INSTANCE = new JvmMetadataVersion(new int[]{1, 1, 15});
public boolean isCompatible() {
return (this.getMajor() != 1 || this.getMinor() != 0) && (this.isStrictSemantics ? this.isCompatibleTo((BinaryVersion)INSTANCE) : this.getMajor() == 1 && this.getMinor() <= 4);
}
//kotlinx.metadata.internal.metadata.deserialization.BinaryVersion.java
protected final boolean isCompatibleTo(@NotNull BinaryVersion ourVersion) {
Intrinsics.checkParameterIsNotNull(ourVersion, "ourVersion");
return this.major == 0 ? ourVersion.major == 0 && this.minor == ourVersion.minor : this.major == ourVersion.major && this.minor <= ourVersion.minor;
}
很明显,我们生成的mv是major=1, minor=9, 没有满足兼容性要求
@Metadata(
mv = {1, 9, 0},
k = 1
}
更新Dagger版到2.46即可,
implementation 'com.google.dagger:dagger:2.46'
implementation 'com.google.dagger:dagger-android:2.46'
kapt 'com.google.dagger:dagger-android-processor:2.46'
kapt 'com.google.dagger:dagger-compiler:2.46'
更新后我们再看看之前报错的地方
这个版本和之前报错的地方metadataOf方法大致一样,
KotlinClassMetadata metadata = KotlinClassMetadata.read(header);
然后这里不会返回null了,因为它也更新了自己的kotlinx-metadata-jvm库,比如0.7.0, 再看read方法:
//kotlinx.metadata.jvm.KotlinClassMetadata.kt
@JvmStatic
fun read(annotationData: Metadata): KotlinClassMetadata {
checkMetadataVersionForRead(annotationData)
return wrapIntoMetadataExceptionWhenNeeded {
when (annotationData.kind) {
CLASS_KIND -> Class(annotationData)
FILE_FACADE_KIND -> FileFacade(annotationData)
SYNTHETIC_CLASS_KIND -> SyntheticClass(annotationData)
MULTI_FILE_CLASS_FACADE_KIND -> MultiFileClassFacade(annotationData)
MULTI_FILE_CLASS_PART_KIND -> MultiFileClassPart(annotationData)
else -> Unknown
}
}
}
即使识别不了k属性,也只会返回Unknown Metadata对象而不是null, checkMetadataVersionForRead()检查版本也只要求生成的major<2即可。
推荐链接
发表评论