首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android: javac对Dalvik

Android: javac对Dalvik
EN

Stack Overflow用户
提问于 2012-07-07 11:09:06
回答 3查看 14.2K关注 0票数 28

我的理解是,Google不喜欢Oracle在Java中使用JRE的许可策略,因此它只是使用自己的JVM规范重写了JRE,该规范模仿JRE,但行为略有不同,特别是在提高效率和安全性方面。

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

如果到目前为止我说的是不正确的话,请从纠正我开始!

现在,如果Android附带了自己的编译器(可能),并以与javac不同的(与Dalvik兼容的)方式编译Java源代码,那么我就能理解为什么某些代码(没有使用Android编译)不会在Android设备上运行:

代码语言:javascript
复制
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来编译安卓应用程序!?看起来我们有这样的:

代码语言:javascript
复制
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的固有特性是什么,这使得无法从Google或Apache这样的项目中运行Java代码。我被告知,为了让骆驼在Dalvik上运行,我必须获得Camel的源代码,然后它必须“使用Android构建”,但我无法弄清楚这意味着什么或暗示了什么。

例如,对于Camel,您可以这样做(简化):

代码语言:javascript
复制
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 .时哪些类型的Java代码不会运行。

编辑:在之前“但骆驼3.0将运行在安卓!”我知道-不是我的问题!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-07 11:27:29

我正在尝试理解当“输入”到Dalvik时哪些类型的Java代码不会运行。

Dalvik在以下方面与其他JVM不同:

  • 它使用特殊的DEX格式来存储应用程序二进制文件和标准Java虚拟机使用的JAR和Pack200格式。谷歌声称DEX导致的二进制文件比JAR小。我认为他们可以用Pack200取得同样的成功,但他们决定在这方面走自己的路。

  • Dalvik JVM被优化为同时运行多个JVM进程。

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

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

  • 如果需要,可以在单个JVM进程中运行多个独立的Android应用程序。

  • 应用程序执行可以“自然”跨越几个Dalvik JVM进程。为了支持这一点,它补充说:

  • 基于Parcel和Parcelable类的特殊对象序列化机制。在功能上,它与标准的Java可序列化功能相同,但会减少数据占用,并可能对类的版本差异更宽容。

  • 基于Android接口定义语言(AIDL)的执行进程间调用(IPC)的Android专用方式

  • 直到Android2.2DalvikJVM不支持JIT编译,这对Android应用程序的性能产生了不利影响。在2.2中添加它可以显著提高常用应用程序的执行速度
票数 30
EN

Stack Overflow用户

发布于 2012-07-07 11:28:14

如果到目前为止我说的是不正确的话,请从纠正我开始!

嗯,嗯.

  • 与Java相比,Dalvik在移动环境中具有技术优势,最显著的是积极使用复制-写内存共享,因此整个VM和标准类库在所有Android应用程序进程之间共享,从而减少了每个进程的净内存占用。有关更多信息,请参阅answer 370305的答案(在我结束此过程时发布)。
  • javac的字节码被交叉编译成Dalvik字节码,作为Android应用程序构建过程的一部分。Java不能执行Dalvik字节码,就像它可以执行/dev/random的输出一样;类似地,Dalvik不能执行Java字节码。

Here is a blog post of mine来自大约两年前,这将涉及到更多的问题。

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

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

没有人能够解释什么是Dalvik固有的,使得无法从像Google或Apache这样的项目运行Java代码

就我个人而言,我从未使用过Google,尽管Roboguice在Android上工作。在回答您的问题之前,我从未听说过Apache,当我发现它不是Perl的Java端口时,我感到很困惑。:-)

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

但是,由于您拒绝具体说明“来自Google Guice或Apache Camel等项目的Java代码”,您有问题,而且由于我对这些项目不太熟悉,因此很难对此作进一步的评论。

票数 25
EN

Stack Overflow用户

发布于 2015-01-13 04:33:07

这幅来自Android官方文档的图片展示了Android的构建过程,它将有助于理解java字节码和dalvik可执行文件之间的区别。

这里我举一个例子来说明其中的一些不同之处。

Hello.java

代码语言:javascript
复制
import java.io.*;
public class Hello {
    public static void main(String[] args) {
        System.out.println("hello world!!!!");
    }
}

使用javacHello.java编译为java字节码Hello.class

代码语言:javascript
复制
$ javac Hello.java

然后使用android中的dx工具将java字节码Hello.class转换为Hello.dex

代码语言:javascript
复制
$ $ANDROID_SDK_ROOT/build-tools/21.1.2/dx --dex --output=Hello.dex Hello.class

然后,使用adbHello.classHello.dex放到Android设备或模拟器中。

代码语言:javascript
复制
$ adb push Hello.class /data/local/tmp/
$ adb push Hello.dex /data/local/tmp/

使用adb shell进入Android设备的shell环境。然后使用命令/system/bin/dalvikvm执行我们刚刚创建的Hello.classHello.dex简单的java程序。

代码语言:javascript
复制
$ 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,它将正常运行。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11374477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档