1

Android 用の私の Java プロジェクトには、いくつかの構成があります。以前はそれらを切り替えて eclipse から手動で apk をビルドしていましたが、最近はもっと簡単にするためにいくつかの ant タスクを開発しました: cmd ファイルを起動すると、すべての構成がビルドされます (毎回構成変数を変更し、リソースを移動し、マニフェストを変更し、等。)。

しかし今日、Android ワークフロー (私の build.xml には ${sdk.dir}/tools/ant/build.xml が含まれています) を使用して ant (javac を使用) によってコンパイルされたコードは、Eclipse の ADT ツールによって生成されたコードとは異なることがわかりました。 . そして違いは致命的です。

コンパイル段階で javac は、一部のファイルに BOM が含まれており、1 つのクラスが (多くの静的配列に対して) 大きすぎると主張しました。すべてのファイルを bom なしで utf8 に変換し、大きなクラスを 2 つに分割し、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 ビルドでは javac 以外のものを使用する必要があると思います。しかし、Google は build.xml で正確に javac を使用しています。ant でビルドするときに、javac の代わりに ADT コンパイラを使用するにはどうすればよいですか?

もちろん、Eclipse でビルドを作成することもできますが、ant スクリプトは、私が 20 分かかるのに 1 分かかります。また、cfg 変数を変更するときにばかげた間違いを犯すことはありません (それらの間にいくつかの依存関係があります)。

前もって感謝します!

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のエクスポート)が機能し、antでコンパイルされたapkはVerifyErrorと言います。

4

1 に答える 1

1

私はこの問題を解決したと思います。

Java バージョンの切り替え、デフォルトの Google Ant タスクの再定義、複数の jdk から別の javac をスタンドアロンとして起動してクラスをコンパイルするのに何時間も費やしました。過去 5 年間、コンソール ツールを使用して Java をコンパイルしたことは一度もなかったので、大変で混乱しました。同じ検証エラーであるjavacで運がありませんでした。

次に、Eclipse と Android のドキュメントを読んだところ、Eclipse で apk をビルドすると、ADT は javac の代わりに Eclipse の JDT (Eclipse Compiler for Java) を使用して Java コードをクラスにコンパイルし、次に dx ツールを使用して dalvik コードを作成することがわかりました。つまり、通常の -compile ant タスクの代わりに JDT を起動する必要がありますね。いいえ、実際にはすべてが簡単です。よくあることですが、最初からやり直しましたが、このコンパイル ツールが必要であることを理解すると、正しい道を歩むことができました。

Eclipse Compiler for Java (JDT ECJ) は、実際の javac よりもはるかにスマートなツールです。これは私にとってはたくさんのパラメーターを備えた新しいツールですが、JDT はかなりクールなant javac adapterを提供し、それを 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 も同様に作成することを確認できます。


したがって、最終的にすべてが2つの簡単なステップになりました。

  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 が正しいコードのコンパイルに失敗する理由についてのアイデアがある場合は、聞きたいです!

于 2013-03-02T00:12:41.827 に答える