#470 "code/removal/all" feature

Paul Sokolovsky

This is early notice (or otherwise I can get too backlogged ;-) ) that I implemented subj feature with hopefully obvious semantics. The code is in my fork https://sourceforge.net/u/pfalcon/proguard/ci/default/log/ (commit messages are detailed), motivation is at http://stackoverflow.com/questions/15671801/java-implibs-aka-jars-devoid-of-actual-code-containing-only-method-definition . It would be nice to get early feedback if this is suitable for mainline. Thanks.


  • Eric Lafortune
    Eric Lafortune

    Nice to see that you're using the code for your own applications.

    Some comments on the code:

    • In ProGuard, all optimizations are enabled by default, so I think your current implementation always removes all instructions.
    • Removing all instructions (including the required return instruction, but leaving in exception handlers, stack map tables, line numbers, etc) leaves a completely invalid CodeAttribute that would break a lot of tools. A simpler and cleaner solution would be to remove the entire CodeAttribute. You could do that by skipping reading or writing it, or by removing it with AttributesEditor#deleteAttribute.
    • Important for me: this is not really an optimization, since the resulting code no longer works.

    Although this is a useful application, it lies outside the scope of ProGuard, so I don't plan to integrate it in the official version. You're free to create your own version though. You could also create a small specialized tool that just reads a jar and writes a stripped jar. That would only take a few lines of code, but admittedly you need to be familiar with the available classes.

    In general, I don't accept external contributions (see Feedback page), for various reasons (fun, complexity, control, ownership, documentation, maintenance,...) I know that this is unusual for an open-source project, but it just works better for me.

  • Thanks for response and hints. I did as you suggested (remove code attribute altogether), but then I found that jar being produced is bigger comparing to what I got yesterday. Dumping a class from old and new jars with jcf-dump (of ubuntu package gcj-jdk) and diffing I get:

    -Reading .class from AbstractAccountAuthenticator1.class.
    +Reading .class from AbstractAccountAuthenticator.class.
     Magic number: 0xcafebabe, minor_version: 0, major_version: 49.
     Access flags: 0x421 public abstract super
     This class: android.accounts.AbstractAccountAuthenticator, super: java.lang.Object
     Interfaces (count: 0):
    -Fields (count: 0):
    +Fields (count: 2):
    +Field name:"a" private final Descriptor: android.content.Context
    +Field name:"b" private Descriptor: android.accounts.AbstractAccountAuthenticator$Transport
    -Methods (count: 10):
    +Methods (count: 12):
     Method name:"<init>" public Descriptor: (android.content.Context)void
    -Attribute "Code", length:12, max_stack:0, max_locals:2, code_length:0
    +Method name:"a" private Descriptor: ()void
     Method name:"getIBinder" public final Descriptor: ()android.os.IBinder
    -Attribute "Code", length:12, max_stack:0, max_locals:1, code_length:0
     Method name:"editProperties" public abstract Descriptor: (android.accounts.AccountAuthenticatorResponse,java.lang.String)android.os.Bundle
    @@ -30,6 +32,7 @@
     Method name:"hasFeatures" public abstract Descriptor: (android.accounts.AccountAuthenticatorResponse,android.accounts.Account,java.lang.String[])android.os.Bundle
     Method name:"getAccountRemovalAllowed" public Descriptor: (android.accounts.AccountAuthenticatorResponse,android.accounts.Account)android.os.Bundle
    -Attribute "Code", length:12, max_stack:0, max_locals:3, code_length:0
    +Method name:"a" static synthetic Descriptor: (android.accounts.AbstractAccountAuthenticator)void
     Attributes (count: 0):

    I.e. code attrs are gone as expected, but now proguard left some non-public fields and method even though I still have only:

    -keepclassmembers public class * {
        public <fields>;
        public <methods>;
        public <init>(***);

    Reverting to old behavior of deleting all instructions didn't help. The only change I did to my system is exactly installing jcf-dump tool (which did pull few other java-related packages, which I didn't record). Uninstalling gcj-jdk doesn't help either. Any idea what can happen here? Thanks again.

    • Eric Lafortune
      Eric Lafortune

      You're probably removing code attributes after the shrinking step, which means that ProGuard is still keeping all dependencies (in this case, non-public fields and methods).

  • Eric Lafortune
    Eric Lafortune

    • status: open --> closed