28

私の理解では、Google は、Java ME で JRE を使用するための Oracle のライセンス ポリシーを気に入らなかったため、JRE を模倣する独自の JVM 仕様を使用して書き直しただけですが、特に物事をより効率的かつ効率的にすることに関しては、動作が少し異なります。より安全に。

したがって、私の理解が正しければ、javacJavaソースコードで実行され、「バイナリ」バイトコードにコンパイルされると、準拠したJVMはDalvikとは異なるバイトコードを解釈することを意味します(場合によっては)。これは、Dalvik と他の (準拠した) JVM との間の固有の違いです。

これまでの私の発言が間違っている場合は、まず訂正してください。

さて、Android に独自のコンパイラが付属しており (そうかもしれません)、Java ソースを とは異なる (Dalvik 準拠の) 方法でjavacコンパイルした場合、一部のコード (Android SDK でコンパイルされていない) がどのように動作しないかを理解できました。 Android デバイス:

MySource.java --> javac --> MySource.class (JRE-compliant) --> JVM --> running Java app
MySource.java --> android-compiler --> MySource.class (Dalvik-compliant) --> Dalvik JVM --> running Android app

しかし、あなたはjavacAndroid アプリのコンパイルに使用しているようです!?!? したがって、次のようになります。

MySource.java --> javac --> MySource.class (JRE-compliant) --> JVM --> running Java app
MySource.java --> javac --> MySource.class (JRE-compliant) --> Dalvik JVM --> running Android app (???)

すべてのソースをバイトコードにコンパイルするために使用される場合javac、Dalvik が一部の種類の Java コードを実行できないのはなぜですか?

私は昨日非常によく似た質問をしましたが、技術的には回答されましたが (私の質問を読み直した後、私は単に十分に具体的ではなかったことがわかりました)、Java コードを実行できなくする Dalvik に固有のものは何かを誰も説明できませんでした。 Google Guice や Apache Camel などのプロジェクトから。Camel を Dalvik で実行するには、Camel のソースを入手してから、「Android SDK でビルド」する必要があると言われましたが、それが何を意味するのか、何を意味するのかを明確にすることはできませんでした。 .

たとえば、Camel を使用すると、次のようになります (簡略化)。

RouteBuilder.java --> javac --> RouteBuilder.class --> jartool --> camel-context-2.9.jar --> JVM --> running Camel ESB
RouteBuilder.java --> javac --> RouteBuilder.class --> jartool --> camel-context-2.9.jar --> Dalvik JVM --> doesn't work !!! (???)

明らかに、Dalvik JVM 内で、特定の種類の Java コードの実行を妨げる何かが発生しています。 Dalvik JVM に「供給」されたときに実行されない Java コードの種類を理解しようとしています。

編集:前に「しかしCamel 3.0はAndroidで実行されます!」私は知っています-私の質問ではありません!

4

3 に答える 3

30
I'm trying to understand what types of Java code will not run when "fed" into the Dalvik JVM.

Dalvik JVM は、次の点で他の JVM とは異なります。

  • 標準の Java 仮想マシンで使用される JAR および Pack200 形式に対して、アプリケーション バイナリを格納するために特別な DEX 形式を使用します。Google は、DEX は JAR よりも小さいバイナリになると主張しています。彼らは Pack200 を使用しても同じ成功を収めることができると思いますが、彼らはこの面で独自の方法を取ることにしました

  • Dalvik JVM は、複数の JVM プロセスを同時に実行するために最適化されました

  • Dalvik JVM は、実行の高速化とバイナリ サイズの削減を目的として、他の JVM のスタック ベースのアーキテクチャに対してレジスタ ベースのアーキテクチャを使用します。

  • 独自の命令セットを使用します (標準の JVM バイトコードではありません)。

  • 単一の JVM プロセス内で複数の独立した Android アプリケーションを (必要に応じて) 実行できます。

  • アプリケーションの実行は、「自然に」複数の Dalvik JVM プロセスにまたがることができます。これをサポートするために、次のように追加します。

    • Parcel および Parcelable クラスに基づく特別なオブジェクトのシリアル化メカニズム。機能的には、標準の Java Serializable と同じ目的を果たしますが、結果としてデータ フットプリントが小さくなり、クラスのバージョンの違いに対してより寛容になる可能性があります。

    • Android Interface Definition Language (AIDL) に基づいてプロセス間呼び出し (IPC) を実行する特別な Android の方法

  • Android 2.2 まで Dalvik JVM は、Android アプリケーションのパフォーマンスに悪影響を与える JIT コンパイルをサポートしていませんでした。2.2 で追加すると、使用頻度の高いアプリケーションの実行速度が大幅に向上します

于 2012-07-07T11:27:29.153 に答える
25

これまでの私の発言が間違っている場合は、まず訂正してください。

うーん、まあ...

  • Dalvik VM には、モバイル環境向けの Java VM よりも技術的な利点があります。最も顕著なのは、コピー オン ライト メモリ共有の積極的な使用です。そのため、VM 全体と標準クラス ライブラリがすべての Android SDK アプリ プロセス間で共有され、プロセスごとの正味コストが削減されます。メモリフットプリント。詳細については、user370305 の回答 (これをまとめている間に投稿) を参照してください。

  • からのバイトコードjavacは、Android アプリケーションのビルド プロセスの一部として Dalvik バイトコードにクロスコンパイルされます。Java VM は、の出力を実行できる以上に、Dalvik バイトコードを実行できません/dev/random。同様に、Dalvik VM は Java バイトコードを実行できません。

これは、約2年前の私のブログ投稿で、追加のポイントになります.

javac を使用してすべてのソースをバイトコードにコンパイルする場合、Dalvik が一部の種類の Java コードを実行できないのはなぜですか?

javacバイトコード出力はクロスコンパイルされているためです。クロスコンパイラ ( dx) は、非常に特殊な形式のjavac出力を処理します。つまり、クラシックjavac(java.sun.com から取得したもの) と Java 1.5 および 1.6 用の OpenJDK では機能しますが、代替コンパイラでは機能しません。 (例: GCJ) であり、少なくとも Java 7 の新しいバイトコードでは動作しません。

Google Guice や Apache Camel などのプロジェクトから Java コードを実行することを不可能にする Dalvik 固有の理由を誰も説明できませんでした。

Roboguiceは Android でも動作しますが、個人的には Google Guice を使用したことはありません。私はあなたの質問の前に Apache Camel について聞いたことがなく、それが Perl の Java ポートではないことにかなり混乱しています。:-)

ランタイム JVM バイトコード生成を行うツールは、Android では機能しません。これは、クロスコンパイラが実行時ではなくコンパイル時にしか利用できないためです。また、ランタイム JVM バイトコード生成ツールで使用される手法と、それらが JVM にそのバイトコードを実行させる方法に慣れていないため、Dalvik に Dalvik バイトコードの任意のチャンクを実行させる同等のフックが Android に存在するかどうかもわかりません。

しかし、あなたが問題を抱えている「Google Guice や Apache Camel のようなプロジェクトの Java コード」を正確に特定することを拒否したため、私はそれらのプロジェクトに精通していないため、これ以上コメントすることは困難です.

于 2012-07-07T11:28:14.637 に答える
13

Android 公式ドキュメントのこの図は、Android APK のビルド プロセスを示しています。Java バイトコードと dalvik 実行可能ファイルの違いを理解するのに役立ちます。 ここに画像の説明を入力

ここでは、いくつかの違いを示すために例を示します。

Hello.java

import java.io.*;
public class Hello {
    public static void main(String[] args) {
        System.out.println("hello world!!!!");
    }
}

Javaバイトコードjavacへのコンパイルに使用Hello.javaHello.class

$ javac Hello.java

次にdx、android sdk のツールを使用して Java バイトコードHello.classHello.dex

$ $ANDROID_SDK_ROOT/build-tools/21.1.2/dx --dex --output=Hello.dex Hello.class

その後、Android デバイスまたはエミュレーターadbに配置Hello.classして使用します。Hello.dex

$ adb push Hello.class /data/local/tmp/
$ adb push Hello.dex /data/local/tmp/

adb shellAndroid デバイスのシェル環境に入るために使用します。次に、コマンドを使用して、/system/bin/dalvikvm作成したばかりの単純な Java プログラムを実行しHello.classHello.dex

$ dalvikvm -Djava.class.path=./Hello.class Hello
java.lang.NoClassDefFoundError: Hello
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn't find class "Hello" on path: ./Hello.class
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:65)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    ... 1 mor
$ dalvikvm -Djava.class.path=./Hello.dex Hello   
hello world!!!!

上記の例では、java バイトコードHello.classdalvikvm苦情エラーを使用する場合、クラスを dalvik 実行可能に変更すると、Hello.dex正常に実行されます。

于 2015-01-13T04:33:07.040 に答える