簡體   English   中英

使用ant構建時,VerifyError,從Eclipse構建時,OK

[英]VerifyError when build with ant, OK when build from Eclipse

我的Android Java項目有幾種配置。 以前,我切換了它們並從eclipse手動構建apk,但是最近我開發了一些ant任務來簡化生活:我啟動cmd文件並構建所有配置(每次更改config var,移動資源,修改清單,等等。)。

但是今天,我發現ant(它使用javac)和android工作流(我的build.xml包含$ {sdk.dir} /tools/ant/build.xml)編譯的代碼與Eclipse中ADT工具生成的代碼不同。 。 區別是致命的。

在編譯階段,javac聲稱某些文件包含BOM,一個類太大(對於許多靜態數組而言)。 我已經將所有文件都轉換為不帶bom的utf8,將大類拆分為兩個,並且javac不再有問題。 很容易。

但是,如果我在4.0.x設備或仿真器(在1.6、2.2、4.1、4.2上運行)上啟動由ant制成的apk,則它將在運行時強制關閉並顯示:

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制作的apk可以在4.0.x上很好地工作! 此外-我從沒見過關於utf bom或編譯時類大小的聲明。

因此,我認為我們應該在ant build中使用比javac更重要的東西。 但是Google在build.xml中完全使用javac。 與ant一起構建時,如何使用ADT編譯器代替javac?

當然,我仍然可以在eclipse中進行構建,但是當我花費20分鍾時,螞蟻腳本花費1分鍾,並且在更改cfg var時,它絕不會犯傻的錯誤(它們之間存在一些依賴關系)。

提前致謝!

UPDT:我懷疑它與我使用的Java版本有某種聯系。 Ant使用1.7 x86 jdk執行,而eclipse使用jdk1.6.0_26 x64。 有人說Dalvik dex無法理解某些Java 1.7字節碼,但我應該檢查一下。

UPDT1:不,我已經刪除了所有jdk,然后安裝了jdk 1.6.0_41 x86和x64,將eclipse設置為1.6.0_41 x64,並將JAVA_PATH設置為jdk 1.6.0_41 x86。 同樣的事情-在eclipse中編譯的apk(Android工具->導出已簽名的apk)有效,螞蟻編譯的apk表示VerifyError。

認為我已經解決了這個問題。

我花了幾個小時來切換Java版本,重新定義默認的Google ant任務,嘗試從幾個jdk作為獨立啟動不同的javac來編譯我的類。 在過去的五年中,我從未使用控制台工具編譯過Java,因此它既困難又令人困惑。 我沒有任何javac的運氣,同樣的驗證錯誤。

然后,我閱讀了Eclipse和Android文檔,發現在eclipse中構建apk時,ADT使用Eclipse的JDT(Java的Eclipse編譯器)而不是javac將Java代碼編譯成類,然后使用dx工具制作dalvik代碼。 因此,我們需要啟動JDT而不是常規的-compant ant任務,對嗎? 不,實際上一切都更容易。 經常發生這種情況,我從頭開始,但是一旦我知道我需要這個編譯工具,我就走對了。

Eclipse Java編譯器(JDT ECJ)比實際的Javac聰明得多。 這對我來說是一個帶有許多參數的新工具,但是JDT提供了非常酷的ant javac適配器 ,我們可以在javac ant任務中使用它-設置“ build.compiler”屬性,然后啟動常規的android ant -compile任務:

<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中沒有這樣的文件! 繼續進行調查,我發現Eclipse Compiler for Java可以獨立下載 要進行此工作,您需要將此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產生了“好”代碼,則ant也會這樣做。


因此,最終所有事情都導致兩個簡單的步驟:

  1. 從內部將org.eclipse.jdt.core_xxxxxx.jar和jdtCompilerAdapter.jar復制到您的ant / lib文件夾中。

  2. 在您的project.properties文件中添加以下內容:

    • java.target = 1.6
    • java.source = 1.6
    • build.compiler = org.eclipse.jdt.core.JDTCompilerAdapter

就這樣!

但是,如果您有想法,為什么eclipse juno軟件包(4.2.2)中的ecj無法編譯正確的代碼,我想聽!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM