The latest version of ProGuard, during the shrinking phase, removes methods that should not be removed. All settings have default values. I kept getting the following error messages:
Exception in thread "main" java.lang.NoSuchMethodError:
a.iterator()Ljava/util/Iterator; at Main.main(Unknown Source)
and finally managed to reduce the error-causing class into a small application. Please note the double inheritance in the interface. The ProGuard version is 4.11 beta8.
import java.util.*;
public class Main
{
// Combined interface to allow anonymous iterable classes
public interface AnonIterable extends Iterable, Iterator {}
public static void main(String[] args)
{
AnonIterable iterable = new AnonIterable()
{
// Iterable method
public Iterator iterator() { return this; }
// Iterator methods
public boolean hasNext() { return false; }
public Object next() { return null; }
public void remove() {}
};
iterable.iterator(); // Crashes with java.lang.NoSuchMethodError :(
}
}
The anonymous inner class, new AnonIterable() {...}, after being processed by ProGuard, loses all its methods. Only empty constructor remains:
public final class a
{
a()
{
}
}
Disabling obfuscation doesn't help. The weird thing is, disabling shrinking doesn't help either. The app still crashes with NoSuchMethodError, but the decompiled version of inner class becomes different:
public final class a
{
a()
{
}
private Iterator a()
{
return this;
}
private static boolean b()
{
return false;
}
private static Object c()
{
return null;
}
private static void d()
{
}
}
Apparently, any connection with the interface's method signatures gets lost at some point.
Thanks for the report. This bug seems to have been fixed by a very recent correction in this area, which you can now find in ProGuard 4.11 beta9.
The new version fixes the problem, much thanks for the quick fix! :)
The new version (4.11 beta9) works great, with one note: comparing to version 4.10, it produces quite some extra glue code. In certain cases, ProGuard generates a whole chain of extra assignments: d2 = d1; d3 = d2; d4 = d3 etc (each variable is used only once). While this may be good for obfuscation purposes, this is not perfect for optimization. But this is just a minor thing.