I'm developing an SDK (Android library), and I have to obfuscate a large part of my code so the customer may not try and play with internal code. My lib is coded in Kotlin, and I used Proguard to obfuscate the code. The problem is that there are still @kotlin.Metadata (runtime) annotations inside the code after compile and obfuscation. With those annotations, retrieving the Java code that originated this "(not-so)obfuscated" bytecode is easy.
I first thought it was my fault, and my project had too many entropy sources that might have induced this behavior, so I made a sample project to prove that the problem did not come from my SDK implementation. I created a new project with AS, and then a lib module with 2 files:
facade.kt is my facade class, the one that I do not wish to obfuscate so that the customer may use it:
package com.example.mylibrary class MyFacade(val internalClass:InternalClass) { fun doSomething() { internalClass.doSomething( firstArgument=1, secondArgument=2 ) } }
and in this sample, internal.kt holds the classes that I want to obfuscate:
package com.example.mylibrary class InternalClass { fun doSomething(firstArgument: Int, secondArgument: Int) { System.out.println("Arguments are : $firstArgument, $secondArgument") } }
The Proguard rules are injected into the gradle project with this release closure:
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
}
And here is proguard-rules.pro
(only one line, nothing more) :
-keep class com.example.mylibrary.MyFacade {*;}
The result: when I ./gradlew clean myLib:assembleRelease
, I do obtain an aar in which my facade is kept, and my internal class has been renamed in 'a', with one method 'a', except that the class is still annotated with Kotlin @Metadata, which holds every information that helps the decompiler retrieve the original class name, the method, attribute, and argument names, etc...
So my code is not so obfuscated at all...
@Metadata(
mv = {1, 1, 7},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\b\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0016\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\u0006\u0010\u0007\u001a\u00020\u0006¨\u0006\b"},
d2 = {"Lcom/example/mylibrary/InternalClass;", "", "()V", "doSomething", "", "firstArgument", "", "secondArgument", "mylibrary_release"}
)
public final class a {
...
}
So my question: is it possible to get rid of those annotations, am I the only one facing this problem, or have I missed something?
*.pro
file fromproguardFiles
, I suspect, that Kotlin Gradle plugin forces annotations to be kept somehow. You might have to use separate Proguard pass to strip those from your jars, — Proguard is just Java library/Ant task, so you can declareclasspath
dependency on it and use it yourself in custom Gradle task/Android Plugin transform. – Stichterjava.lang.AbstractMethodError: abstract method "java.lang.Object kotlin.jvm.functions.Function0.invoke()"
I got cryptic errors like this one, which seems to be linked to the way java interacts with kotlin bytecode... I'm doomed. – Eats-libraryjars
list wrong or something like that. Make sure, that you have both "-dontskip*" options in Proguard config! – Stichter-keepattributes !*Metadata*
? – Melon