gson 元INF/版本/9/模块信息类:损坏的类文件?(此功能需要ASM 6)

wmtdaxz3  于 2022-11-06  发布在  其他
关注(0)|答案(5)|浏览(197)

我在使用Bouncycastle时遇到了问题,这只在运行:lint任务时出现。
一般来说,这似乎是Java 9字节码版本53.0 /ASM版本冲突。
以下是相关性:

// https://mvnrepository.com/artifact/org.bouncycastle
implementation "org.bouncycastle:bcprov-jdk15on:1.64"
implementation "org.bouncycastle:bcpkix-jdk15on:1.64"

这会导致:lint任务引发处理错误:

> Task :mobile:lint
Error processing bcpkix-jdk15on-1.64.jar:META-INF/versions/9/module-info.class: broken class file? (This feature requires ASM6)
Error processing bcprov-jdk15on-1.64.jar:META-INF/versions/9/module-info.class: broken class file? (This feature requires ASM6)
  • 元INF/版本/9/模块信息类:损坏的类文件?(此功能需要ASM 6)*

这同样适用于:

// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation "com.google.code.gson:gson:2.8.6"

1.4.1升级到1.4.2-native-mt后,情况又是一样的:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2-native-mt"

文件类型:损坏的类文件?(模块需要ASM 6)

nmpmafwu

nmpmafwu1#

如前所述,这是在Java 9中引入的,Android不支持。你可以只使用packagingOptions来删除这些类。

android {
    packagingOptions {
        exclude "**/module-info.class"
    }
}

这应该不会影响实际执行的代码,并且还应该删除用于lint检查的类,因为lint正在处理字节码。

slwdgvem

slwdgvem2#

更新:请查看我当前的answer,它解决了这个问题。

此答案仅作为Gradle脚本编写的示例保留。
使用旧版本(可能是使用Java 8构建的)时,不会出现此类处理错误:

// https://mvnrepository.com/artifact/org.bouncycastle
implementation "org.bouncycastle:bcprov-jdk15on:1.60"
implementation "org.bouncycastle:bcpkix-jdk15on:1.60"

// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation "com.google.code.gson:gson:2.8.5"

这个问题显然是在版本1.61/2.8.6(可能是用Java 9构建的)中引入的。
当Google把一个人带回到自己的答案时,这是令人讨厌的,这并不是一个真正的答案。我没有保留版本或编辑JAR,而是编写了一个DeleteModuleInfoTask和一个shell脚本,它自动从任何给定的Java依赖项中删除module-info.class
由于commandLine只接受一个命令,因此几乎必须调用一个脚本。这应该是一个定制Exec任务的好例子。
对于Linux:module_info.sh考虑versions/9/module-info.classmodule-info.class


# !/usr/bin/env bash

GRADLE_CACHE_DIR=$HOME/.gradle/caches/modules-2/files-2.1
ZIP_PATHS=(META-INF/versions/9/module-info.class module-info.class)   
if [[ $# -ne 3 ]]; then
  echo "Illegal number of parameters"
  exit 1
else
  if [ -d "$GRADLE_CACHE_DIR" ]; then
    DIRNAME=${GRADLE_CACHE_DIR}/$1/$2/$3
    if [ -d "$DIRNAME" ]; then
      cd ${DIRNAME} || exit 1
      find . -name ${2}-${3}.jar | (
        read ITEM;
        for ZIP_PATH in "${ZIP_PATHS[@]}"; do
          INFO=$(zipinfo ${ITEM} ${ZIP_PATH} 2>&1)
          if [ "${INFO}" != "caution: filename not matched:  ${ZIP_PATH}" ]; then
            zip ${ITEM} -d ${ZIP_PATH} # > /dev/null 2>&1
          fi
        done
      )
      exit 0
    fi
  fi
fi

对于Windows:module_info.bat依赖于7-Zip

@echo off
REM delete module.info from JAR file - may interfere with the local IDE.
for /R %USERPROFILE%\.gradle\caches\modules-2\files-2.1\%1\%2\%3\ %%G in (%2-%3.jar) do (
  if exist %%G (
      7z d  %%G META-INF\versions\9\module-info.class > NUL:
      7z d  %%G versions\9\module-info.class > NUL:
      7z d  %%G module-info.class > NUL:
  )
)

更新:经过一些测试后,我得出结论,在Windows上开发时,手动编辑文件可能更好,因为Android Studio和Java会锁定JAR,这将随后阻止编辑并留下临时文件。
文件tasks.gradle提供了DeleteModuleInfoTask

import javax.inject.Inject

abstract class DeleteModuleInfoTask extends Exec {
    @Inject
    DeleteModuleInfoTask(String dependency) {
        def os = org.gradle.internal.os.OperatingSystem.current()
        def stdout = new ByteArrayOutputStream()
        def stderr = new ByteArrayOutputStream()
        ignoreExitValue true
        standardOutput stdout
        errorOutput stderr
        workingDir "${getProject().getGradle().getGradleUserHomeDir()}${File.separator}caches${File.separator}modules-2${File.separator}files-2.1${File.separator}${dependency.replace(":", File.separator).toString()}"
        String script = "${getProject().getRootDir().getAbsolutePath()}${File.separator}scripts${File.separator}"
        def prefix = ""; def suffix = "sh"
        if (os.isWindows()) {prefix = "cmd /c "; suffix = "bat"}
        String[] item = dependency.split(":")
        commandLine "${prefix}${script}module_info.${suffix} ${item[0]} ${item[1]} ${item[2]}".split(" ")
        // doFirst {println "${commandLine}"}
        doLast {
            if (execResult.getExitValue() == 0) {
                if (stdout.toString() != "") {
                    println "> Task :${project.name}:${name} ${stdout.toString()}"
                }
            } else {
                println "> Task :${project.name}:${name} ${stderr.toString()}"
            }
        }
    }
}

示例用法:

// Bouncycastle
tasks.register("lintFixModuleInfoBcPkix", DeleteModuleInfoTask, "org.bouncycastle:bcpkix-jdk15on:1.64")
lint.dependsOn lintFixModuleInfoBcPkix

tasks.register("lintFixModuleInfoBcProv", DeleteModuleInfoTask, "org.bouncycastle:bcprov-jdk15on:1.64")
lint.dependsOn lintFixModuleInfoBcProv

// GSON
tasks.register("lintFixModuleInfoGson", DeleteModuleInfoTask, "com.google.code.gson:gson:2.8.6")
lint.dependsOn lintFixModuleInfoGson

// Kotlin Standard Library
tasks.register("lintFixModuleInfoKotlinStdLib", DeleteModuleInfoTask, "org.jetbrains.kotlin:kotlin-stdlib:1.4.32")
lint.dependsOn lintFixModuleInfoKotlinStdLib

请确保仅为单个模块注册这些任务。
根据resmon“资源监视器”〉“关联句柄”,studio64java可能持有JAR文件的锁,因此7-Zip可能只能在Android Studio和Java关闭时编辑存档;至少它可以很好地用于Linux上的CI。

sg24os4d

sg24os4d3#

文件module-info.class是自Java 9以来引入的Java模块系统的一部分。根据Android IssueTracker上的this issue,该漏洞自Android Studio 3.4以来已得到修复。

hk8txs48

hk8txs484#

我收到以下错误消息:

Error processing C:\Users\mypc\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.8.6\9180733b7df8542621dc12e21e87557e8c99b8cb\gson-2.8.6.jar:module-info.class: broken class file? (This feature requires ASM6)

如果不使用Android Studio等开发系统,就会出现此错误。我使用的是Gradle 6.1.1。
我防止错误如下:
1.打开错误消息中命名的文件gson-2.8.6.jar
1.删除文件module-info.class,该文件位于根目录中

o2rvlv0m

o2rvlv0m5#

有一个更简单的解决方案。基本上,问题可以被确定为“使用Java 8运行Gradle,同时处理使用Java 9构建的文件”。我的新方法是使用Java 11构建(GitHub Actions也使用Java 11构建,Gradle 6.7.1目前最多支持Java 15)。

  • 使用sudo dnf install java-11-openjdk安装Java 11之后
  • alternatives --display java将列出要使用的JDK。

例如:/usr/lib/jvm/java-11-openjdk-11.0.11.0.9-0.el8_3.x86_64

顺便说一句,使用JDK 11进行构建还可以修复此警告:
当前JDK版本1.8.0_172-b11存在一个错误(https://bugs.openjdk.java.net/browse/JDK-8007720),阻止Room进行增量。请考虑使用JDK 11+或Android Studio 3.5+附带的嵌入式JDK。
“Android Studio 3.5+附带的嵌入式JDK”仍然是Java 8...

相关问题