2013-03-01 38 views
1

我的Android項目有幾個配置。以前,我通過手動切換並從Eclipse構建apk,但最近我開發了一些ant任務,以使我的生活變得更加輕鬆:我啓動cmd文件,並構建所有配置(每次更改配置變量,移動資源,修改清單,等等。)。用Ant生成VerifyError,從Eclipse生成時確定OK

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

在編譯階段,javac聲稱某些文件包含BOM,並且一個類太大(對於很多靜態數組)。我已經將所有文件轉換爲utf8 w/o bom,將大類拆分爲兩個,並且javac沒有更多的問題。很容易。

但是如果我推出螞蟻造APK 4.0.x的設備或仿真器上(而作品上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或class size的聲明。

所以我認爲我們應該在ant build中使用比javac更遠的東西。但Google在其build.xml中正好使用了javac。 如何在使用ant構建時使用ADT編譯器而不是javac?

當然,我仍然可以在eclipse中構建,但是當我花費20分鐘時,ant腳本花費1分鐘,並且它在改變cfg vars(它們之間存在一些相關性)時從未犯下愚蠢的錯誤。

在此先感謝!

更新: 我懷疑它以某種方式與我使用的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。同樣的事情 - apk在Eclipse中編譯(Android工具 - >導出簽名apk)的作品,螞蟻編譯apk說VerifyError。

+0

什麼是你默認的stackTrace? – 2013-03-01 18:46:29

+0

它是調用堆棧,它並不重要:主要的是它在第一次嘗試訪問類MySomeClass時在運行時崩潰。所以我試圖弄清楚的主要問題是 - 在ant build中啓動javac和adt執行此操作之間有什麼區別? – Tertium 2013-03-01 18:52:48

回答

1

認爲我解決了這個問題。

我花了幾個小時切換java版本,重新定義默認的谷歌螞蟻任務,試圖從幾個獨立的jdk啓動不同的javac作爲獨立編譯我的類。在過去的五年裏,我從來沒有用控制檯工具編譯java,所以很困難和困惑。我沒有運氣與任何javac,相同的驗證錯誤。然後我閱讀Eclipse和Android文檔,發現當我們在eclipse中構建apk時,ADT使用Eclipse的JDT(Eclipse Compiler for Java)而不是javac將java代碼編譯成類,然後使用dx工具來製作dalvik代碼。 所以我們需要啓動JDT而不是普通的編譯螞蟻任務,對吧?不,實際上一切都比較容易。正如我經常發生的那樣,我從最後開始,但一旦我明白我需要這個編譯工具,我就正確了。用於Java的Eclipse編譯器(JDT ECJ)比實際的javac更聰明的工具。對於我來說這是一個新的工具,但是JDT提供了很酷的ant javac adapter,我們可以在javac ant任務中使用它 - set「build」。編譯器」屬性,然後啓動正常的Android螞蟻-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編譯器爲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反編譯),所以我認爲問題出現在結果類文件中。我想知道什麼是heck,但是ev en無法想象要尋找什麼。

無論如何,還有更多。當你查看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從它裏面的螞蟻/ lib文件夾。

  2. 添加下列您project.properties文件:

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

這一切!

但是,如果你有什麼想法,爲什麼ecj來自eclipse juno包(4.2.2)無法編譯正確的代碼,我想傾聽!

+0

我收到一條消息,提示沒有找到類:org.eclipse.jdt.core.JDTCompilerAdapter Android的tools/ant目錄中沒有lib文件夾,你在哪裏放置了罐子?你有沒有重新命名它們? – schwiz 2013-10-01 21:40:44