I have a large function (I know, see below) that breaks proguard during its optimizing pass. I’d like to keep both the long function and the optimization. Is this possible? Is there some way to persuade proguard to handle larger functions?
The code compiles under Eclipse and runs on an Android device. It is the proguard optimization step of my release build script that fails. If I remove 30 odd lines from the function it builds fine, but obviously does not run correctly.
My large function is a switch function that emulates a state machine. There are about five separate but related variables that adjust in different ways as the state machine progresses. I could break up my function but the coupling between the sub functions would be undesirable.
The stack trace from the Null Pointer Exception is:
[proguard] Shrinking...
[proguard] Removing unused program classes and class elements...
[proguard] Original number of program classes: 176
[proguard] Final number of program classes: 173
[proguard] Optimizing...
[proguard] Unexpected error while evaluating instruction:
[proguard] Class = [com/.../Screen]
[proguard] Method = [switchToView$26d62a66(Lcom/...;Ljava/lang/String;)V]
[proguard] Instruction = [20] iload v4
[proguard] Exception = [java.lang.NullPointerException] (null)
[proguard] Unexpected error while performing partial evaluation:
[proguard] Class = [com/.../Screen]
[proguard] Method = [switchToView$26d62a66(Lcom/.../View;Ljava/lang/String;)V]
[proguard] Exception = [java.lang.NullPointerException] (null)
BUILD FAILED
/Users/colin/Android/.../build.xml:527: java.lang.NullPointerException
at proguard.evaluation.Variables.iload(Variables.java:228)
at proguard.evaluation.Processor.visitVariableInstruction(Processor.java:645)
at proguard.classfile.instruction.VariableInstruction.accept(VariableInstruction.java:306)
at proguard.optimize.evaluation.PartialEvaluator.evaluateSingleInstructionBlock(PartialEvaluator.java:729)
at proguard.optimize.evaluation.PartialEvaluator.evaluateInstructionBlock(PartialEvaluator.java:575)
at proguard.optimize.evaluation.PartialEvaluator.visitExceptionInfo(PartialEvaluator.java:1063)
at proguard.classfile.visitor.ExceptionHandlerFilter.visitExceptionInfo(ExceptionHandlerFilter.java:67)
at proguard.classfile.attribute.CodeAttribute.exceptionsAccept(CodeAttribute.java:186)
at proguard.optimize.evaluation.PartialEvaluator.evaluateExceptionHandlers(PartialEvaluator.java:1003)
at proguard.optimize.evaluation.PartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(PartialEvaluator.java:540)
at proguard.optimize.evaluation.PartialEvaluator.visitCodeAttribute0(PartialEvaluator.java:221)
at proguard.optimize.evaluation.PartialEvaluator.visitCodeAttribute(PartialEvaluator.java:180)
at proguard.optimize.evaluation.LivenessAnalyzer.visitCodeAttribute(LivenessAnalyzer.java:195)
at proguard.optimize.evaluation.VariableOptimizer.visitCodeAttribute(VariableOptimizer.java:102)
at proguard.classfile.attribute.CodeAttribute.accept(CodeAttribute.java:101)
at proguard.classfile.ProgramMethod.attributesAccept(ProgramMethod.java:79)
at proguard.classfile.attribute.visitor.AllAttributeVisitor.visitProgramMember(AllAttributeVisitor.java:95)
at proguard.classfile.util.SimplifiedVisitor.visitProgramMethod(SimplifiedVisitor.java:91)
at proguard.classfile.ProgramMethod.accept(ProgramMethod.java:71)
at proguard.classfile.ProgramClass.methodsAccept(ProgramClass.java:439)
at proguard.classfile.visitor.AllMethodVisitor.visitProgramClass(AllMethodVisitor.java:47)
at proguard.classfile.ProgramClass.accept(ProgramClass.java:281)
at proguard.classfile.ClassPool.classesAccept(ClassPool.java:114)
at proguard.optimize.Optimizer.execute(Optimizer.java:764)
at proguard.ProGuard.optimize(ProGuard.java:325)
at proguard.ProGuard.execute(ProGuard.java:114)
at proguard.ant.ProGuardTask.execute(ProGuardTask.java:279)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
at com.android.ant.IfElseTask.execute(IfElseTask.java:120)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:390)
at org.apache.tools.ant.Target.performTasks(Target.java:411)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
at org.apache.tools.ant.Main.runBuild(Main.java:809)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Optimizing long methods can take a long time, but it shouldn’t fail. This error message is an indication of a bug in ProGuard. You should check if it hasn’t been fixed in the latest version (4.6 at this time of writing). Otherwise, you should report it on ProGuard’s bug tracker. If you can provide a test case that allows me to reproduce the problem, I’ll look into it.