我的Android java项目有几种配置。以前我切换它们并手动从eclipse构建apk,但最近我开发了几个ant任务让我的生活更轻松:我启动cmd文件并构建所有配置(每次更改配置变量,移动资源,修改清单,等)。
但今天我发现由ant(它使用javac)和android工作流编译的代码(我的build.xml包含$ {sdk.dir} /tools/ant/build.xml)与代码不同由Eclipse中的ADT工具生成。并且差异是致命的。
在编译阶段,javac声称某些文件包含BOM,而且一个类太大(对于许多静态数组)。我已经将所有文件转换为utf8 w / o bom,将大类拆分为两个,javac没有更多问题。很容易。
但是,如果我在4.0.x设备或模拟器上启动ant-made apk(同时适用于1.6,2.2,4.1,4.2),它会在运行时关闭并说:
03-01 09:15:16.247: W/dalvikvm(1993): VFY: register1 v3 type 17, wanted 18
03-01 09:15:16.247: W/dalvikvm(1993): VFY: rejecting opcode 0xc8 at 0x0023
03-01 09:15:16.247: W/dalvikvm(1993): VFY: rejected Lcom/myproj/MySomeClass;.doThing (I)V
03-01 09:15:16.247: W/dalvikvm(1993): Verifier rejected class Lcom/myproj/MySomeClass;
03-01 09:15:16.247: W/System.err(1993): java.lang.VerifyError: com/myproj/MySomeClass
...
<stack here>
...
但eclipse-adt-made apk在4.0.x上工作得相当好!此外 - 我从未在编译时看到关于utf bom或类大小的adt声明。
所以我假设我们应该在ant build中使用比javac更好的东西。但Google在其build.xml中使用了完全正确的javac。 在使用ant构建时,我们如何使用ADT编译器代替javac?
当然我仍然可以在eclipse中进行构建,但是当我花20分钟时,ant脚本花费1分钟,而且在更改cfg变量时它们从未犯过愚蠢的错误(它们之间存在一些依赖关系)。
提前致谢!
UPDT: 我怀疑它与我使用的java版本有某种联系。 Ant以1.7 x86 jdk执行,而eclipse使用jdk1.6.0_26 x64。有人说Dalvik dex不了解一些java 1.7字节码,但我应该检查一下。
UPDT1:不,我删除了所有jdks,然后安装了jdk 1.6.0_41 x86和x64,将eclipse工作设置为1.6.0_41 x64并将JAVA_PATH设置为jdk 1.6.0_41 x86。同样的事情 - 在eclipse(Android工具 - &gt;导出签名的apk)编译的apk工作,蚂蚁编译apk说VerifyError。
答案 0 :(得分:1)
认为我已经解决了这个问题。
我花了几个小时来切换java版本,重新定义默认的google ant任务,尝试从几个jdk中独立启动不同的javac来编译我的类。在过去的五年里,我从来没有使用控制台工具编译java,因此很难和混乱。我对任何javac没有运气,同样的验证错误。
然后我读了Eclipse和Android文档,发现当我们在eclipse中构建apk时,ADT使用Eclipse的JDT(Eclipse Compiler for Java)代替javac将java代码编译成类,然后使用dx工具制作dalvik代码。 所以我们需要启动JDT而不是普通的编译ant任务,对吧?不,实际上一切都更容易。因为它经常发生,我从最后开始,但一旦我明白我需要这个编译工具,我是在正确的方式。
Eclipse Compiler for Java(JDT ECJ)是比实际javac更智能的工具。这对我来说是一个新工具,有很多参数,但是JDT提供了非常酷的ant javac adapter,我们可以在javac ant任务中使用它 - 设置“build.compiler”属性,然后启动正常的android ant -compile任务:< / p>
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter" />
<javac encoding="${java.encoding}" source="1.6" target="1.6" debug="true" extdirs=""
includeantruntime="false" destdir="${out.classes.absolute.dir}"
bootclasspathref="project.target.class.path"
verbose="${verbose}" classpathref="project.javac.classpath"
fork="${need.javac.fork}" >
<src path="${source.absolute.dir}" />
<src path="${gen.absolute.dir}" />
<compilerarg line="${java.compilerargs}" />
</javac>
但除非你有ecj.jar,否则这不会奏效。日食中没有这样的文件!继续调查我发现Eclipse Compiler for Java可以是downloaded as standalone。要完成这项工作,您需要将此jar复制到ant / lib文件夹。但奇怪的是 - ecj 4.2.2编译代码具有相同的验证问题。幸运的是我已经尝试过ecj 3.5.1 - 它有效!但是我不满意 - 我仍然不能说为什么ecj 4.2.2在3.5.1没有帮助。如果我升级eclipse会编译坏类怎么办?我比较了字节代码 - 它略有不同(由jd-gui反编译),所以我认为问题在于产生类文件。我想知道什么是哎呀,但我甚至无法想象要寻找什么。
无论如何,还有更多。当你查看eclipse / plugins文件夹时,你会看到一个名为“org.eclipse.jdt.core_3.6.2.v_A76_R36x.jar”的文件。它包含jdtCompilerAdapter.jar文件(因为jar是一个zip存档)。如果你将它复制到ant / lib然后复制org.eclipse.jdt.core_xxxxxx.jar文件本身,你得到的是当前eclipse版本所具有的完全相同的编译器!瞧!这样你就可以确定如果eclipse成为一个“好”的代码 - 蚂蚁也会这样做。
所以最后一切都产生了两个简单的步骤:
将org.eclipse.jdt.core_xxxxxx.jar和jdtCompilerAdapter.jar从里面复制到你的ant / lib文件夹。
将以下内容添加到project.properties文件中:
这就是全部!
但是如果你有想法为什么来自eclipse juno package(4.2.2)的ecj无法编译正确的代码我想听!