-
Notifications
You must be signed in to change notification settings - Fork 472
Description
I am encountering a runtime AbstractMethodError when using Functional Interfaces that have been obfuscated/renamed by ProGuard.
Issue description & cause
The issue appears to be a desynchronization between the renamed method in the Interface definition and the name operand in the InvokeDynamic instruction. ProGuard renames the method in the interface (e.g., run -> a), but fails to update the InvokeDynamic instruction that generates the lambda.
The instruction:
invokedynamic run ()Ltest/TestFI; LambdaMetafactory.metafactory { ()Ljava/lang/String;, { invokestatic, test/Main.a, ()Ljava/lang/String; }, ()Ljava/lang/String; }
with test.TestFI being:
@FunctionalInterface
public interface TestFI {
String a();
}Consequently, LambdaMetafactory generates a runtime proxy class that implements the original method name, but the JVM attempts to call the obfuscated method name defined in the interface, causing a crash.
Subsequent crash
I observe the following crash at runtime:
java.lang.AbstractMethodError: Receiver class test.TestFI$$Lambda/0x0000 does not define or inherit an implementation of the resolved method 'abstract java.lang.Object a()'
Steps to reproduce & proof
- Define a Functional Interface with a single method (e.g., execute()).
- Use a lambda expression that implements this interface.
- Run ProGuard with obfuscation enabled.
- Execute the obfuscated JAR.
- Crash: The application crashes when the lambda is invoked.
I managed to confirm this by getting it to run without any issues by manually patching the name operand in the indy instruction to match the obfuscated name.
Version info
- proguard v7.8.2 or lower (also observed with v7.7 and possibly earlier versions)
- Any Java version, used OpenJDK 64-Bit Server VM (build 24+36-3646, mixed mode, sharing) for the demonstration above.