Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard removes Anonymous class in Anonymous class in Java

I have a issue that Proguard is not working when you declare a anonymous class within a anonymous class. This is what it looks like in a basic example:

public class Class1 {
  public void function1 (){
     new Class2(){
        @Override
        public void function2(){
          new Class3(){
            @Override
            public void function3(){
              // do something
            }
          }
        }
     }
  }
}

During a gradle build script proguard is being executed. Now i get the following error:

 my.package.Class1$2$1: can't find enclosing method 'void function2()' in program class my.package.Class1$2

If I change the code to just have 1 "level" of anonymous classes proguard is finishing without errors. This works:

public class Class1 {
  public void function1 (){
      Class3 class3Instance = new Class3(){
            @Override
            public void function3(){
              // do something
            }
      }
      new Class2(){
        @Override
        public void function2(){
           //do something with class3Instance  
        }
     }
  }
}

The project is a android project, though as far as I know that should not matter.

I tried all different kind of -keep rules for Class1, but nothing worked. Is this not supported by Proguard or do I have to add a rule to get it to work?

UPDATE 1:

As requested the structure if the interface used for the anonymous classes. The interface for Class2 is defined as follows:

public class Class2IntefaceEnclosingClass {
    public interface Class2 {
        void function2();
    }
}

The interface for Class3 is slightly different:

public interface Class3IntefaceEnclosingInterface {
    interface Class3 {
        void function3();
    }
}

Note: I can not change the layout of the interfaces since they are provided by android.

like image 550
Arne Fischer Avatar asked Sep 27 '16 09:09

Arne Fischer


People also ask

Can anonymous class be passed as a parameter?

Yes, by adding an initializer method that returns 'this', and immediately calling that method: int myVariable = 1; myButton. addActionListener(new ActionListener() { private int anonVar; public void actionPerformed(ActionEvent e) { // How would one access myVariable here? // It's now here: System.

What is true about anonymous class in Java?

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.

Are anonymous objects possible in Java?

Generally, when creating an object in Java, you need to assign a name to the object. But the anonymous object in Java allows you to create an object without any name assigned to that object. So, if you want to create only one object in a class, then the anonymous object would be a good approach.


1 Answers

You can try to use @Keep annotation above function1(), function2() and function3().

public class Class1 {
  @Keep
  public void function1 (){
     new Class2(){
        @Keep
        @Override
        public void function2(){
          new Class3(){
            @Keep
            @Override
            public void function3(){
              // do something
            }
          }
        }
     }
  }
}
like image 171
Sebastian Staszyński Avatar answered Sep 21 '22 17:09

Sebastian Staszyński