安卓:javac vs Dalvik

安卓:javac vs Dalvik,java,android,javac,dalvik,Java,Android,Javac,Dalvik,我的理解是,谷歌不喜欢Oracle在JavaMe中使用JRE的许可政策,所以它只是重写了 它使用自己的JVM规范,该规范模仿JRE,但行为有点不同,特别是当它出现时 让事情变得更高效、更安全 因此,如果我的理解是正确的,这意味着当javac在一些Java源代码上运行并编译成“二进制”时 字节码,兼容JVM将解释与Dalvik不同的字节码(在某些情况下)。这是内在的 Dalvik和其他(兼容)JVM之间的差异 如果到目前为止我说的任何话都是错误的,请先纠正我 现在,如果Android自带了自己的编

我的理解是,谷歌不喜欢Oracle在JavaMe中使用JRE的许可政策,所以它只是重写了 它使用自己的JVM规范,该规范模仿JRE,但行为有点不同,特别是当它出现时 让事情变得更高效、更安全

因此,如果我的理解是正确的,这意味着当
javac
在一些Java源代码上运行并编译成“二进制”时 字节码,兼容JVM将解释与Dalvik不同的字节码(在某些情况下)。这是内在的 Dalvik和其他(兼容)JVM之间的差异

如果到目前为止我说的任何话都是错误的,请先纠正我

现在,如果Android自带了自己的编译器(可能),并以不同的方式编译了Java源代码(符合Dalvik) 这样,我就可以理解一些代码(不是用androidsdk编译的)是如何不能在一台计算机上运行的 安卓设备:

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所固有的是什么 这使得无法从GoogleGuice或ApacheCamel等项目运行Java代码。有人告诉我,为了让Camel在Dalvik上运行,我必须获得Camel的源代码,然后它必须“使用Android SDK构建”,但我无法弄清楚这意味着什么或意味着什么

例如,对于Camel,您有以下内容(简化):

显然,Dalvik JVM内部发生了一些事情,阻止它运行某些类型的Java代码。 我试图了解什么类型的Java代码在“输入”到Dalvik JVM时不会运行。

编辑:在之前的“但是骆驼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格式来存储应用程序二进制文件,而不是JAR 以及标准Java虚拟机使用的Pack200格式。谷歌 声称DEX产生的二进制文件比JAR小。我想他们 可以使用Pack200获得同样的成功,但他们决定继续使用 在这方面有自己的做法

  • Dalvik JVM针对运行多个JVM进程进行了优化 同时

  • Dalvik JVM使用基于寄存器的体系结构,而不是基于堆栈的体系结构 其他JVM的体系结构,旨在加速执行和 减少二进制大小

  • 它使用自己的指令集(不是标准的JVM字节码)

  • 你可以运行(如果需要)几个独立的Android应用程序 在单个JVM进程中

  • 应用程序执行可以跨越多个Dalvik JVM进程 “自然”。支持这一点吗 加上:

    • 基于Parcel和Parcelable的特殊对象序列化机制 上课。从功能上讲,它与标准Java具有相同的用途 可序列化,但会导致更小的数据占用,并且可能会对类版本的差异更加宽容

    • 基于Android的进程间调用(IPC)的特殊执行方式 Android界面定义语言(AIDL)

  • 直到Android 2.2 Dalvik JVM才支持JIT编译 对Android应用程序性能产生不利影响。将其添加到2.2中 显著提高了常用应用程序的执行速度

如果到目前为止我说的任何话都是错误的,请先纠正我

嗯,嗯

  • Dalvik VM在移动环境中比Java VM具有技术优势,最显著的是积极使用写时拷贝内存共享,因此整个VM和标准类库在所有Android SDK应用程序进程之间共享,从而减少了每进程的净内存占用。有关更多信息,请参阅user370305的答案(在我结束本文时发布)

  • 作为Android应用程序构建过程的一部分,来自
    javac
    的字节码被交叉编译成Dalvik字节码。Java虚拟机不能执行Dalvik字节码,正如它不能执行
    /dev/random
    的输出一样;类似地,Dalvik VM无法执行Java字节码

从大约两年前开始,这就涉及到了更多的问题

如果使用javac将所有源代码编译成字节码,那么为什么Dalvik不能运行某些类型的Java代码

因为
javac
字节码输出是交叉编译的。交叉编译器(
dx
)处理非常特殊风格的
javac
输出,这意味着虽然它可以与经典的
javac
(您可以从java.sun.com获得)和OpenJDK for java 1.5和1.6一起工作,但它不会与其他编译器(例如GCJ)一起工作,至少,不会与来自Java7的任何新字节码一起工作

没有人能够解释Dalvik的固有特性是什么,使得它无法从GoogleGuice或ApacheCamel这样的项目运行Java代码

就我个人而言,我从未使用过谷歌Guice,尽管它在Android上工作。在您提出问题之前,我从来没有听说过ApacheCamel,我很困惑地发现它不是Perl的Java端口。:-)

任何生成运行时JVM字节码的工具都无法在Android上工作,因为交叉编译器只在编译时可用,而不是在运行时。另外,我不熟悉运行时JVM字节码生成工具使用的技术,以及它们如何让JVM执行字节码,因此我不知道Android中是否存在等效的挂钩,让Dalvik运行任意的Dalvik字节码块

但是,
I'm trying to understand what types of Java code will not run when "fed" into the Dalvik JVM.
import java.io.*;
public class Hello {
    public static void main(String[] args) {
        System.out.println("hello world!!!!");
    }
}
$ javac Hello.java
$ $ANDROID_SDK_ROOT/build-tools/21.1.2/dx --dex --output=Hello.dex Hello.class
$ adb push Hello.class /data/local/tmp/
$ adb push Hello.dex /data/local/tmp/
$ 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!!!!