Compiling with Proguard gives SimException: "local variable type mismatch"

When I compile my Android application with Proguard enabled, I get the following error:

-dex: [echo] Converting compiled files and external libraries into /home/ka/dev/workspace/ImPress/build/classes.dex... [apply] [apply] UNEXPECTED TOP-LEVEL EXCEPTION: [apply] com.android.dx.cf.code.SimException: local variable type mismatch: attempt to set or access a value of type java.io.File using a local variable of type java.lang.Object[]. This is symptomatic of .class transformation tools that ignore local variable information. [apply] at com.android.dx.cf.code.BaseMachine.throwLocalMismatch(BaseMachine.java:550) [apply] at com.android.dx.cf.code.BaseMachine.getLocalTarget(BaseMachine.java:405) [apply] at com.android.dx.cf.code.BaseMachine.storeResults(BaseMachine.java:532) [apply] at com.android.dx.cf.code.ValueAwareMachine.run(ValueAwareMachine.java:197) [apply] at com.android.dx.cf.code.RopperMachine.run(RopperMachine.java:291) [apply] at com.android.dx.cf.code.Simulator$SimVisitor.visitLocal(Simulator.java:608) [apply] at com.android.dx.cf.code.BytecodeArray.parseInstruction(BytecodeArray.java:526) [apply] at com.android.dx.cf.code.Simulator.simulate(Simulator.java:99) [apply] at com.android.dx.cf.code.Ropper.processBlock(Ropper.java:684) [apply] at com.android.dx.cf.code.Ropper.doit(Ropper.java:639) [apply] at com.android.dx.cf.code.Ropper.convert(Ropper.java:252) [apply] at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:252) [apply] at com.android.dx.dex.cf.CfTranslator.translate0(CfTranslator.java:131) [apply] at com.android.dx.dex.cf.CfTranslator.translate(CfTranslator.java:85) [apply] at com.android.dx.command.dexer.Main.processClass(Main.java:369) [apply] at com.android.dx.command.dexer.Main.processFileBytes(Main.java:346) [apply] at com.android.dx.command.dexer.Main.access$400(Main.java:59) [apply] at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:294) [apply] at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244) [apply] at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:130) [apply] at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:108) [apply] at com.android.dx.command.dexer.Main.processOne(Main.java:313) [apply] at com.android.dx.command.dexer.Main.processAllFiles(Main.java:233) [apply] at com.android.dx.command.dexer.Main.run(Main.java:185) [apply] at com.android.dx.command.dexer.Main.main(Main.java:166) [apply] at com.android.dx.command.Main.main(Main.java:90) [apply] ...at bytecode offset 00000006 [apply] locals[0000]: Lcom/officemax/impress/ui/library/task/DocumentBrowserTask; [apply] locals[0001]: [Ljava/lang/Object; [apply] locals[0002]: <invalid> [apply] ...while working on block 0006 [apply] ...while working on method doTaskJob:([Ljava/lang/Object;)Lcom/kaciula/utils/ui/BasicTaskResponse; [apply] ...while processing doTaskJob ([Ljava/lang/Object;)Lcom/kaciula/utils/ui/BasicTaskResponse; [apply] ...while processing com/officemax/impress/ui/library/task/DocumentBrowserTask.class [apply] [apply] 1 error; aborting 

How can I fix this problem?

+43
android proguard
Apr 18 '11 at 9:50 a.m.
source share
4 answers

The actual part of Proguard ends, but then dex can no longer convert the received bytecode. Dex considers LocalVariableTable . Eric Lafortune is the best source for explaining why (see His answer).

The problem goes away if you not only confuse, but also skip the optimization step ( -dontoptimize ). But you want to have this to reduce size. Another way to solve this is to clear the debug flags in javac and in dex . The only problem is that then you would not have the correct stacks either. You will get stacktrace lines without information about the file or line numbers, for example:

 net.lp.collectionista.domain.items.book.BookItem.getCoverImageForFormField(Unkno‌​wn Source) 

You can do this by adding debug="false" to the javac tag in ant main-rules.xml (you can copy the part in build.xml ). This will set the javac -g:none flag. You also need to configure dex, and this is more difficult to do in the provided ant template. I copied the dex-helper macro, made sure it is being used, and added a condition tag surrounding the dex calls:

  <echo>Converting compiled files and external libraries into ${intermediate.dex.file}...</echo> <if condition="debug"> <then> <apply executable="${dx}" failonerror="true" parallel="true"> <arg value="--dex" /> <arg value="--output=${intermediate.dex.file}" /> <extra-parameters /> <arg line="${verbose.option}" /> <arg path="${out.dex.input.absolute.dir}" /> <path refid="out.dex.jar.input.ref" /> <external-libs /> </apply> </then> <else> <apply executable="${dx}" failonerror="true" parallel="true"> <arg value="--dex" /> <arg value="--output=${intermediate.dex.file}" /> <arg value="--no-locals" /><!-- otherwise dex fails on the proguard bytecode --> <extra-parameters /> <arg line="${verbose.option}" /> <arg path="${out.dex.input.absolute.dir}" /> <path refid="out.dex.jar.input.ref" /> <external-libs /> </apply> </else> </if> 

It does --no-locals .

To reduce the loss of stack information, you can use, respectively, for information about the line number and the names of classes and methods:

 -keepattributes SourceFile, LineNumberTable -keep,allowshrinking,allowoptimization class * { <methods>; } 

That way you can do partial obfuscation and still have equivalent good stacks. I still suggest that you create and store the mapping files after release.

On top of that, you should not specify -keepattributes LocalVariableTable,LocalVariableTypeTable and equally -keepparameternames (if you obfuscate, this in itself can also cause problems). Note that the second implies the first, even if it may not be clear from its name that it affects attributes.

Personally, and taking into account other problems with Proguard, I decided to do obfuscation, but reduced the loss of stack information. I haven't tried @plowman's suggestion yet.

For more information, you can find versioned files here:

+14
Nov 02 '11 at 18:52
source share

I encountered the same problem after adding the -dontobfuscate flag to the proguard.cfg file.

In the end, it turned out that I needed to add this to my optimization:

 !code/allocation/variable 

This makes my full optimization line look like this:

 -optimizations !field/removal/writeonly,!field/marking/private,!class/merging/*,!code/allocation/variable 
+91
Sep 28 '11 at 18:20
source share

This is a bug in ProGuard. His optimization step sometimes does not completely correctly update the optional debugging attributes LocalVariableTable and LocalVariableTypeTable inside the class files. Dalwick VM explicitly checks debugging attributes and rejects class files if they are incompatible.

You should check if the latest version of ProGuard is fixed. Otherwise, you must remove the local variable names and types from the class files. You can ask the java compiler not to generate them (for example, "javac -g: none"). You can also ask ProGuard not to store them (do not specify "-keepattributes LocalVariableTable, LocalVariableTypeTable").

+22
Apr 19 '11 at 20:00
source share

I just got this on Windows "Android Studio", and disabling Instant Run made everything work again.

+5
May 12 '16 at 6:38
source share



All Articles