Method of lambda expression passed as an instance of an interface defined in obfuscated library is not obfuscated correclty
patrick96 opened this issue · 0 comments
When building against an obfuscated library (providing its mapping file using -applymapping
), I have noticed that lambda expressions which represent an implementation of an interface do not get obfuscated correctly when that interface is part of the obfuscated library.
At runtime this produces an AbstractMethodError
because the interface's single member method was renamed, but the lambda instance still has the unobfuscated method name.
Steps to Reproduce
The idea is to build an obfuscated library defining an interface and an application defining a lambda
lib_stripped.jar
Interface.java
interface Interface {
void doSomething(int x);
}
Lib.java
public class Lib {
public static void call(Interface i, int x) {
System.out.println("methods:");
for (var m : i.getClass().getDeclaredMethods()) {
System.out.println("\t" + m);
}
i.doSomething(x);
}
}
lib.pro
-injars lib.jar
-outjars lib_stripped.jar
-libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
-printmapping lib_stripped.map
-useuniqueclassmembernames
-dontoptimize
-dontshrink
To build lib_stripped.jar
:
javac Lib.java Interface.java
jar cf lib.jar Lib.class Interface.class
proguard-7.4.2/bin/proguard.sh -include lib.pro
app_stripped.jar
Main.java
public class Main {
public static void main(String[] args) {
Lib.call((x) -> { System.out.println(x + 1); }, 100);
}
}
app.pro
-injars app.jar
-outjars app_stripped.jar
-libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
-libraryjars lib.jar(!META-INF/versions/**,!module-info.class)
-applymapping lib_stripped.map
-printmapping app_stripped.map
-useuniqueclassmembernames
-dontoptimize
-dontshrink
-keep public class Main {
public static void main(java.lang.String[]);
}
To build app_stripped.jar
:
javac -cp lib.jar Main.java
jar -c -f app.jar -e Main.class Main.class
proguard-7.4.2/bin/proguard.sh -include app.pro
Now when we run this, we get an AbstractMethodError and see that the method defined on the passed object is still called doSomething
:
$ java -cp lib_stripped.jar:app_stripped.jar Main
methods:
public void Main$$Lambda/0x000071a1e8001800.doSomething(int)
Exception in thread "main" java.lang.AbstractMethodError: Receiver class Main$$Lambda/0x000071a1e8001800 does not define or inherit an implementation of the resolved method 'abstract void a(int)' of interface a.
at b.a(Unknown Source)
at Main.main(Unknown Source)
Additional context
If you run with the unobfuscated jars, you get the expected output:
$ java -cp lib.jar:app.jar Main
methods:
public void Main$$Lambda/0x00007baadc001800.doSomething(int)
101