使用Proguard进行编译会产生SimException:“局部变量类型不匹配"; [英] Compile with Proguard gives SimException: "local variable type mismatch"

查看:80
本文介绍了使用Proguard进行编译会产生SimException:“局部变量类型不匹配";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在启用Proguard的情况下编译Android应用程序时,出现以下错误:

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

如何解决此问题?

推荐答案

Proguard的实际部分完成了,但是dex无法再转换结果字节码. Dex认为LocalVariableTable不正确.埃里克·拉福尔敦(Eric Lafortune)是解释原因的更好资料(请参阅他的回答).

The actual Proguard part finishes, but then dex cannot convert the resulting bytecode anymore. Dex considers the LocalVariableTable incorrect. Eric Lafortune is the better source to explain why (see his answer).

如果您不仅不进行混淆,而且还跳过优化步骤(-dontoptimize),问题就会消失.但是,您希望具有此功能以减小尺寸.解决此问题的另一种方法是在javacdex中删除调试标志.唯一的问题是,那么您也将没有适当的堆栈跟踪.您将获得没有源文件信息或行号的stacktrace行,例如:

The problem goes away if you not only don't obfuscate, but also skip the optimization step (-dontoptimize). But you want to have this for the size reduction. Another way to solve it is to drop the debug flags in javac and in dex. Only problem is that then you wouldn't have proper stacktraces either. You will get stacktrace lines without source file info or line numbers such as:

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

您可以通过在蚂蚁main-rules.xmljavac标记中添加debug="false"来做到这一点(您可能希望先将零件复制到build.xml).这将设置一个标志javac -g:none.您还必须配置dex,在提供的ant模板中很难做到这一点.我复制了dex-helper宏,确保正在使用它,并在dex调用周围添加了条件标签:

You can do this by adding debug="false" in the javac tag in the ant main-rules.xml (you may want to copy the part to a build.xml first). This will set a flag javac -g:none. You also have to configure dex and this is harder to do in the provided ant template. I copied the dex-helper macro, made sure it was 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>

--no-locals做到的.

要减少堆栈跟踪信息的丢失,您可以分别将其用于行号信息以及类和方法名信息:

To mitigate the loss of stacktrace information you can use, respectively for line number information and class and method names information:

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

这样,您可以进行部分混淆,并且仍然具有等效的良好堆栈跟踪.我仍然建议您在发布时创建并保留映射文件.

This way you can do partial obfuscation, and still have equivalent good stacktraces. I still suggest you create and keep the mapping files upon release though.

最重要的是,您不应该同时指定-keepattributes LocalVariableTable,LocalVariableTypeTable-keepparameternames(如果进行混淆的话,它本身也可能会给您带来麻烦).请注意,第二个隐含了第一个隐含的含义,尽管从名称上可能不清楚它会影响属性.

On top of all this you shouldn't specify -keepattributes LocalVariableTable,LocalVariableTypeTable and equally -keepparameternames (if you do obfuscate, this by itself might get you into troubles as well). Note that the second implies the first, even though it may not be clear from its name that it affects attributes.

就个人而言,鉴于Proguard的其他问题,我选择进行混淆处理,但可以减轻堆栈跟踪信息的丢失.我还没有尝试过@plowman的建议.

Personally, and in view of other problems with Proguard, I chose to do the obfuscation but mitigate the loss of stacktrace information. I haven't tried @plowman's proposal yet.

有关更多详细信息,您可以在这里找到我的版本控制的项目文件:

For more details you can find my version controlled project files here:

build.xml

这篇关于使用Proguard进行编译会产生SimException:“局部变量类型不匹配";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆