raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.3k stars 808 forks source link

ByteBuddyJarTask fails on multi-release JAR files #1710

Closed LarsBodewig closed 2 months ago

LarsBodewig commented 2 months ago

I tried using the ByteBuddyJarTask of the gradle plugin with a custom byte-buddy plugin to transform a local jar. However the plugin fails on jar files that contain class files under META-INF/versions.

The jar file I used: org.lwjgl:lwjgl:3.3.3

My gradle build file with a minimal custom plugin (simplified from my actual script):

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath 'net.bytebuddy:byte-buddy-gradle-plugin:1.15.0'
        classpath 'net.bytebuddy:byte-buddy:1.15.0'
        classpath file('libs/lwjgl-3.3.3.jar')
    }
}

import net.bytebuddy.build.Plugin
import net.bytebuddy.build.gradle.ByteBuddyJarTask
import net.bytebuddy.description.type.TypeDescription
import net.bytebuddy.dynamic.ClassFileLocator
import net.bytebuddy.dynamic.DynamicType

class SimplePlugin implements Plugin {
    @Override
    void close() throws IOException {
    }

    @Override
    DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) {
        System.out.println(typeDescription.getName())
        return builder
    }

    @Override
    boolean matches(TypeDescription typeDefinitions) {
        return typeDefinitions != null
    }
}

tasks.create("byteBuddyJarlwjgl333jar", ByteBuddyJarTask) {
      source = file("libs/lwjgl-3.3.3.jar")
      target = file("transformedLibs/lwjgl-3.3.3.jar")
      classPath = project.getBuildscript().getConfigurations().getByName(ScriptHandler.CLASSPATH_CONFIGURATION)
      transformation {
          plugin = SimplePlugin
      }
}

The stacktrace is

> Task :byteBuddyJarlwjgl333jar FAILED
Could not locate Java target version, build is JDK dependant: 21
META-INF.versions.10.org.lwjgl.system.MathUtil

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':byteBuddyJarlwjgl333jar'.
> Failed to transform class META-INF.versions.10.org.lwjgl.system.MathUtil: [java.lang.IllegalStateException: Illegal type name: META-INF.versions.10.org.lwjgl.system.MathUtil for class META-INF.versions.10.org.lwjgl.system.MathUtil]> Task :jarBuild FAILED

* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':test:byteBuddyJarlwjgl333jar'.
        [...gradle internals...]
Caused by: java.lang.IllegalStateException: Failed to transform class META-INF.versions.10.org.lwjgl.system.MathUtil: [java.lang.IllegalStateException: Illegal type name: META-INF.versions.10.org.lwjgl.system.MathUtil for class META-INF.versions.10.org.lwjgl.system.MathUtil]
        at net.bytebuddy.build.Plugin$Engine$ErrorHandler$Failing$1.onError(Plugin.java:1186)
        at net.bytebuddy.build.Plugin$Engine$ErrorHandler$Compound.onError(Plugin.java:1438)
        at net.bytebuddy.build.Plugin$Engine$Listener$ForErrorHandler.onError(Plugin.java:2022)
        at net.bytebuddy.build.Plugin$Engine$Listener$Compound.onError(Plugin.java:2151)
        at net.bytebuddy.build.Plugin$Engine$Default$Preprocessor$Resolved.call(Plugin.java:4906)
        at net.bytebuddy.build.Plugin$Engine$Default$Preprocessor$Resolved.call(Plugin.java:4852)
        at net.bytebuddy.build.Plugin$Engine$Dispatcher$ForSerialTransformation.accept(Plugin.java:3904)
        at net.bytebuddy.build.Plugin$Engine$Default.apply(Plugin.java:4699)
        at net.bytebuddy.build.gradle.AbstractByteBuddyTask.apply(AbstractByteBuddyTask.java:505)
        at net.bytebuddy.build.gradle.AbstractByteBuddyTask.doApply(AbstractByteBuddyTask.java:373)
        at net.bytebuddy.build.gradle.ByteBuddyJarTask.apply(ByteBuddyJarTask.java:174)

As far as I can tell my custom plugin executes successfully, as the output contains the "type name" META-INF.versions.10.org.lwjgl.system.MathUtil, however the ByteBuddyJarTask fails before going to the next type. I suppose byte buddy wrongly identifies the type name since it should not contain META-INF.versions.10.

raphw commented 2 months ago

The name of a class is derived from its path, and in this case this is incorrect as its a MR jar file. I will need to see how I can process those locations.

LarsBodewig commented 2 months ago

Sorry for the late feedback, but looks good to me now.