私の理解では、GoogleはJava MEでJREを使用するためのOracleのライセンスポリシーを好まなかったため、JREを模倣する独自のJVM仕様を使用して書き直しましたが特に、物事をより効率的かつ安全にすることに関しては、動作が少し異なります。
したがって、私の理解が正しければ、javac
がJavaソースコードで実行され、「バイナリ」バイトコードにコンパイルされると、準拠したJVMはDalvikとは異なるバイトコードを解釈することを意味します(ある場合)。これは、Dalvikと他の(準拠した)JVMの本質的な違いです。
私がこれまでに言ったことが間違っている場合は、私を訂正することから始めてください!
さて、Androidに独自のコンパイラが付属していて(おそらく)、Javaソースをjavac
とは異なる(Dalvik準拠の)方法でコンパイルした場合、コード(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
ただし、javac
を使用してAndroidアプリをコンパイルしているようです!?!?したがって、次のようになります。
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コードを実行できないのはなぜですか?
私は昨日非常によく似た質問をしましたが、技術的には答えられましたが(質問を読み直した後、私は単に十分に具体的ではなかったことがわかりました)、実行を不可能にするDalvikに固有のものを誰も説明できませんでしたJava GoogleGuiceやApacheCamelなどのプロジェクトのコード。 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で実行されます!」私は知っています-私の質問ではありません!
I'm trying to understand what types of Java code will not run when "fed" into the Dalvik JVM.
Dalvik JVMは、次の点で他のJVMとは異なります:
アプリケーションのバイナリを格納するために特別なDEX形式を使用しますが、標準のJava仮想マシンで使用されるJARおよびPack200形式です。DEXの結果はJARよりも小さいと主張しています。Pack200を使用できると思います。同じ成功ですが、彼らはこの側面で独自の道を進むことにしました
Dalvik JVMは、複数のJVMプロセスを同時に実行するために最適化されました
Dalvik JVMは、実行を高速化し、バイナリサイズを削減することを目的として、他のJVMのレジスタベースのアーキテクチャとスタックベースのアーキテクチャを使用します。
独自の命令セット(標準のJVMバイトコードではない)を使用します
(必要に応じて)単一のJVMプロセス内で複数の独立したAndroidアプリケーションを実行できます)
アプリケーションの実行は、複数のDalvikJVMプロセスに「自然に」及ぶ可能性があります。これをサポートするために、次のように追加します。
ParcelクラスとParcelableクラスに基づく特別なオブジェクトシリアル化メカニズム。機能的には、標準と同じ目的を果たしますJavaシリアライズ可能ですが、データフットプリントが小さくなり、クラスのバージョンの違いに対して寛容になる可能性があります
特別なAndroid Androidインターフェイス定義言語(AIDL)に基づくプロセス間呼び出し(IPC)を実行する方法
Android 2.2 Dalvik JVMはJITコンパイルをサポートしていなかったため、Androidアプリケーションのパフォーマンスに悪影響を及ぼしました。2.2で追加すると、頻繁に使用されるアプリケーションの実行速度が大幅に向上します。
私がこれまでに言ったことが間違っている場合は、私を訂正することから始めてください!
うーん、まあ...
Dalvik VMは、モバイル環境のJava VM、特にコピーオンライトの積極的な使用よりも技術的な利点があります。メモリ共有を書き込むため、VMおよび標準クラスライブラリ全体がすべてのAndroid SDKアプリプロセス間で共有され、プロセスごとの正味のメモリフットプリントが削減されます。user370305を参照してください。詳細については、回答(これをまとめている間に投稿されました)。
javac
のバイトコードは、Androidアプリケーションビルドプロセスの一部として、Dalvikバイトコードにクロスコンパイルされます。Java VMは、/dev/random
の出力を実行できる以上にDalvikバイトコードを実行できません。同様に、Dalvik VMは実行できませんJavaバイトコード。
これが私のブログ投稿です 約2年前からの追加のポイントになります。
Javacを使用してすべてのソースをバイトコードにコンパイルする場合、Dalvikが一部のタイプのJavaコードを実行できないのはなぜですか?
javac
バイトコード出力はクロスコンパイルされているためです。クロスコンパイラ(dx
)は、非常に特殊なjavac
出力を処理します。つまり、従来のjavac
(Java.Sunから取得したもの)で動作します。 .com)およびOpenJDK for Java 1.5および1.6、代替コンパイラ(GCJなど)では機能せず、少なくともJava 7。
googleGuiceやApacheCamelなどのプロジェクトからJavaコードを実行できなくなるのは、Dalvikに固有のものであるということを誰も説明できませんでした。
個人的には、Google Guiceを使用したことはありませんが、 Roboguice Androidで動作します。私はあなたの質問の前にApacheCamelについて聞いたことがなく、それがJava Perlのポートではないことを見つけるのにかなり混乱しています。:-)
クロスコンパイラーは実行時ではなくコンパイル時にのみ使用可能であるため、ランタイムJVMバイトコード生成を実行するツールはAndroidでは機能しません。また、ランタイムJVMバイトコード生成ツールで使用される手法と、JVMにそのバイトコードを実行させる方法に慣れていないため、Androidに同等のフックが存在するかどうかはわかりません。 Dalvikは、Dalvikバイトコードの任意のチャンクを実行します。
ただし、問題のある「GoogleGuiceやApacheCamelなどのプロジェクトのJavaコード」を正確に指定することを拒否し、これらのプロジェクトに精通していないため、これ以上コメントすることは困難です。
Android公式ドキュメントからのこの写真は、Android APKのビルドプロセスを示しています。これは、Javaバイトコードとdalvik実行可能ファイル。
ここでは、いくつかの違いを示す例を示します。
Hello.Java
import Java.io.*;
public class Hello {
public static void main(String[] args) {
System.out.println("hello world!!!!");
}
}
javac
を使用してHello.Java
をJavaバイトコードHello.class
にコンパイルします
$ javac Hello.Java
次に、dx
ツールをAndroid sdk convert Java bytecode Hello.class
to Hello.dex
から
$ $Android_SDK_ROOT/build-tools/21.1.2/dx --dex --output=Hello.dex Hello.class
その後、adb
を使用してHello.class
とHello.dex
をAndroidデバイスまたはエミュレーターに配置します。
$ adb Push Hello.class /data/local/tmp/
$ adb Push Hello.dex /data/local/tmp/
adb Shell
を使用してAndroidデバイスのシェル環境に入ります。次に、コマンド/system/bin/dalvikvm
を使用して、単純なJavaプログラムを実行します。 Hello.class
とHello.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.class
、dalvikvm
苦情エラーを使用する場合、クラスをdalvik実行可能ファイルHello.dex
に変更すると、正しく実行されます。