Elye
Elye

Reputation: 60251

Why is an in used function still shown in usage.txt of proguard output?

I have the following code

class MainActivity : AppCompatActivity() {
    private val obfuscatedClass = MyObfuscatedClass()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        obfuscatedClass.usedFunc()
    }
}

class MyObfuscatedClass {
    fun usedFunc() {}
    fun unusedFunc() {}
}

With a normal proguard, I generate the usage.txt file, showing the unusedFunc() there

com.example.myobfuscateretracetest.MyObfuscatedClass:
    public final void unusedFunc()

This is correct, as the usage.txt file is meant to show the class or removed function during compilation as mentioned in

However, if I change my class to a lazy as shown below,

class MainActivity : AppCompatActivity() {
    private val obfuscatedClass by lazy {
        MyObfuscatedClass()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        obfuscatedClass.usedFunc()
    }
}

class MyObfuscatedClass {
    fun usedFunc() {}
    fun unusedFunc() {}
}

When I check the usage.txt, I notice that both also shown, just in a different section

com.example.myobfuscateretracetest.MyObfuscatedClass:
    public final void unusedFunc()

// ... other sections

com.example.myobfuscateretracetest.MyObfuscatedClass:
    public final void usedFunc()

Why is the usedFunc() still being shown in the usage.txt?

Upvotes: 0

Views: 498

Answers (2)

Chris.Jenkins
Chris.Jenkins

Reputation: 13139

Probably related to this:

The java compiler inlines primitive constants and String constants (static final fields). ProGuard would therefore list such fields as not being used in the class files that it analyzes, even if they are used in the source files. We can add a -keepclassmembers option that keeps those fields a priori, in order to avoid having them listed:

-keepclassmembers class * {
    static final %                *;
    static final java.lang.String *;
}

Try adding that to your proguard.pro file and run it again should stop printing out usages of those static members (which are stripped but not that we can see)

Upvotes: 0

Elye
Elye

Reputation: 60251

Apparently the odd behavior of scenario 2 above only happen when using

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

If I use the non-optimize default proguard, then it's alright.

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

Perhaps the optimize proguard does more advanced optimization, though the function is used, but it still got optimized away?

Upvotes: 0

Related Questions