使用 Proguard 编译会给出 SimException: “局部变量类型不匹配”
当我在启用 Proguard 的情况下编译 Android 应用程序时,出现以下错误:
-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
如何解决此问题?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是 ProGuard 中的一个错误。它的优化步骤有时不会完全正确地更新类文件内的可选“LocalVariableTable”和“LocalVariableTypeTable”调试属性。 Dalvik VM 显式检查调试属性,如果不一致则拒绝类文件。
您应该检查最新版本的 ProGuard 是否修复了该问题。否则,您应该从类文件中删除局部变量名称和类型。您可以要求 java 编译器不要生成它们(例如“javac -g:none”)。您还可以要求 ProGuard 不要保留它们(不要指定“-keepattributes LocalVariableTable,LocalVariableTypeTable”)。
This is a bug in ProGuard. Its optimization step sometimes doesn't update the optional "LocalVariableTable" and "LocalVariableTypeTable" debug attributes inside class files entirely correctly. The Dalvik VM explicitly checks the debug attributes and rejects the class files if they are inconsistent.
You should check if the latest version of ProGuard fixes the problem. Otherwise, you should remove local variable names and types from the class files. You can ask the java compiler not to generate them (e.g. "javac -g:none"). You can also ask ProGuard not to keep them (don't specify "-keepattributes LocalVariableTable,LocalVariableTypeTable").
实际的 Proguard 部分完成,但 dex 无法再转换生成的字节码。 Dex 认为
LocalVariableTable
不正确。埃里克·拉福图恩(Eric Lafortune)是解释原因的更好来源(请参阅他的回答)。如果您不仅不进行混淆,而且跳过优化步骤(
-dontoptimize
),那么问题就会消失。但你想用它来缩小尺寸。解决此问题的另一种方法是删除javac
和dex
中的调试标志。唯一的问题是,你也不会有正确的堆栈跟踪。您将获得没有源文件信息或行号的堆栈跟踪行,例如:您可以通过在 ant
的
(您可能需要先将该部分复制到javac
标记中添加debug="false"
来实现此目的main-rules.xmlbuild.xml
)。这将设置一个标志javac -g:none
。您还必须配置 dex,这在提供的 ant 模板中很难做到。我复制了dex-helper
宏,确保它正在被使用,并在 dex 调用周围添加了一个条件标记:由
--no-locals
执行此操作。为了减少堆栈跟踪信息的丢失,您可以分别使用行号信息以及类和方法名称信息:
这样您可以进行部分混淆,并且仍然具有等效的良好堆栈跟踪。不过,我仍然建议您在发布时创建并保留映射文件。
最重要的是,您不应该指定
-keepattributes LocalVariableTable,LocalVariableTypeTable
以及同样的-keepparameternames
(如果您进行混淆,这本身也可能会给您带来麻烦) 。请注意,第二个隐含第一个,尽管从其名称中可能无法清楚地看出它影响属性。就个人而言,考虑到 Proguard 的其他问题,我选择进行混淆,但减少堆栈跟踪信息的丢失。我还没有尝试过@plowman 的建议。
有关更多详细信息,您可以在此处找到我的版本控制项目文件:
proguard.cfg
build.xml
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).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 injavac
and index
. 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:You can do this by adding
debug="false"
in thejavac
tag in the antmain-rules.xml
(you may want to copy the part to abuild.xml
first). This will set a flagjavac -g:none
. You also have to configure dex and this is harder to do in the provided ant template. I copied thedex-helper
macro, made sure it was being used, and added a condition tag surrounding the dex calls:It's the
--no-locals
that does it.To mitigate the loss of stacktrace information you can use, respectively for line number information and class and method names information:
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.
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.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:
proguard.cfg
build.xml
我刚刚在 Windows 的 Android Studio 上重新出现了这个问题,禁用 Instant Run 使一切再次正常运行。
I just had this resurface on Windows' Android Studio, and disabling Instant Run made things work again.
在将 -dontobfuscate 标志添加到我的 proguard.cfg 文件后,我遇到了同样的问题。
最终的解决方案是我需要将其添加到我的优化中:
这使我的完整优化字符串如下所示:
I ran into the same problem after adding the -dontobfuscate flag to my proguard.cfg file.
The solution ended up being that I needed to add this to my optimizations:
This makes my complete optimization string look like this: