突然,一个奇怪的想法浮现在脑海。如果 Google Play Market 上有 Java 应用程序,那么理论上它应该可以在任何有 Java 机器的地方工作。它也应该适用于 Windows。
问题:
是否可以在 Windows 上从 Google Play Market 安装 Java 应用程序?
突然,一个奇怪的想法浮现在脑海。如果 Google Play Market 上有 Java 应用程序,那么理论上它应该可以在任何有 Java 机器的地方工作。它也应该适用于 Windows。
问题:
是否可以在 Windows 上从 Google Play Market 安装 Java 应用程序?
免责声明:
我不是 Android 开发专家,因为 我几乎将所有时间都花在了 Web 应用程序上,然而,这个话题对我来说非常有趣,所以我将尝试详细描述它(尽可能多地对我个人感兴趣)。
Java作为一种编程语言:
Java是一种编程语言,即 一些合同/规范的描述(描述和相关行为(例如,未定义行为的不可接受性)),可以通过各种方式实现。
例如,没有人禁止在 Java 语言之上编写自己的运行时环境,即 类似于 Java 的运行时环境,即 作为源代码将使用来自特定版本的 Java 语言的特性(特征)。在这种情况下,您将面临一项艰巨的任务:保持与各种(至少是最流行的)处理器架构和操作系统 API 的兼容性。
此外,在特定情况下,您自己的实现甚至不必类似于 JVM:它不必编译为字节码(见下文),而是直接将源代码编译为机器码(
native machine code),即 使用在许多其他语言中使用的更传统的方法(例如Go,C,C++,Swift, ...)。为了了解所有功能和复杂性(由于系统的实现方式有所不同),您需要了解应用程序如何在 Android 及其他系统上运行的原理:
经典的类 JVM 实现:
一个典型的经典(非Android)Java应用程序的生命周期可以描述如下:
source code-(compiler)->bytecode-(JVM)->native machine code.让我们详细说明一个具体的例子:
.java-(javac)->.class-(HotSpot)->native machine code:java作为源代码;javac作为用Java编写的源代码的编译器bytecode;HotSpot(来自 Oracle)作为 JVM,即 将字节码命令运行时/解释为特定 CPU 的机器码命令,即 一个特定的处理器,其核心执行native machine code应用程序的机器代码 ( );machine code- 针对特定处理器架构和操作系统 API 的一组指令。让我们更详细地分析一下:
source code(源代码)——基于 JVM 编程语言的程序代码:.java-file - Java 代码;.kt-file - Kotlin 代码;.clj-file - Clojure 代码;.scala-file - Scala 代码;.groovy-file - Groovy 代码;compiler- 源代码bytecode的编译器(编译器的选择肯定取决于源代码中使用的编程语言):javacCLI 工具;kotlincCLI 工具scalacCLI 工具groovycCLI 工具bytecode-规范中描述的一组指令,由 JVM 执行:.class-file - 将源代码编译成字节码的一组指令;.class文件中,不管它是否Top Level Class存在;native machine code(机器代码)- 由处理器执行的一组指令(针对特定的处理器架构和 OS API):在特定处理器架构的指令中解释字节码的结果;
一般情况下,在一个JVM的框架内,需要支持所有用于执行代码的CPU的命令;
通常,为了支持跨操作系统的 API,JVM 提供商(例如 Oracle)通常为每个操作系统发布单独的 JVM 发行版,每个发行版仅支持其发布的操作系统的 API(以最小化单个 JVM 发行版的大小)。
JVM实现:
您可能已经猜到有许多 JVM 实现,每个实现都独立负责将所有标准
bytecode转换为每个处理器架构的特定标准native machine code。为清楚起见,我将为您提供最流行的 JVM 实现的大致列表:
HotSpot VM(来自甲骨文);OpenJVM;MSJVM/Microsoft VM;IBM JVM;JRockit;Dalvik(来自安卓公司):Android Runtime,又名,ART(来自谷歌):DalvikVM (Dalvik被ARTAndroid 5.0 “Lollipop”取代);在 JVM 规范的每一个实现中,都独立解决了以下问题:
经典类JVM应用的打包(打包):
在打包(打包)经典的类JVM应用方面,有以下几种选择:
public static void main(String[] args),其指示在 中描述META-INF/MANIFEST.MF;META-INF/ejb-jar.xml通过注解(通过 Java SPI(服务提供者接口),特别是Java Annotation Processing API )将 EJB 模块的描述添加到中;WEB-INF/web.xml通过注解(通过 Java SPI(服务提供者接口),特别是Java Annotation Processing API )向 中添加 Web 模块的描述;有关更多详细信息,请参见此处和此处。
Android 类 JVM 实现:
在为 Android 开发应用程序时,来自 Android, Inc. 的人。(Android 的创造者,后来被 Google 吸收)选择使用已经非常流行的 Java 编程语言,从某个版本(例如 java 6)实现其功能,并以一种或另一种方式定期更新它们(例如,爪哇 8). 在此处、此处和此处查看更多信息。
因此,他们并没有从头开始发明一种编程语言(就像 Apple 在创建自己的语言时所做的那样
Swift),但他们极大地改变了执行环境。现在代码的生命周期开始根据具体实现有所不同。考虑一个使用标准 Android 构建工具的示例:
source code-(classic JVM compiler)->bytecode-(dexer)->dex-(Android JVM)->machine code.让我们详细说明一个具体的例子
java-(javac)->.class-(dexer)->classes.dex-(Dalvik / ART)->machine code:java作为源代码;javac作为经典 JVM 的经典源代码编译器bytecode;.class- 以经典 JVM 字节码格式存储命令的文件(JVM 规范中描述的标准指令);dexer作为将经典 JVM 字节码转换为专有字节码格式的实用程序 -dex(Dalvik 可执行文件);classes.dex(Dalvik 可执行文件)- 一个文件(通常是一个),它以 JVM Dalvik 和 ART 的专有字节码格式存储命令;Android Runtime(ART) 和Dalvik(by Google) 作为 JVM,即 将 dex(专有字节码)命令运行时/解释为机器码(详见此处):Dalvik使用范式JIT(Just-In-Time),即 在程序执行期间编译为机器代码;Dalvik已被Android RuntimeAndroid 5.0“棒棒糖”取代;Android Runtime(ART) 使用AOT( Ahead-Of-Time ) 范式,即 在程序执行之前编译为机器代码(在 Android 的情况下 - 在.apk从 play 市场安装期间):Android Runtime使用文件dex(Dalvik 可执行文件),因此向后兼容DalvikAndroid 中的专有字节码应用程序;machine code- 针对特定处理器架构的一组指令。注意:应该理解,例如使用 tools 工具包
Jack时,构建过程看起来会有点不同:.java->.jack->.dex,但是在这个答案的框架内,我们可能不会偏离标准工具的考虑,所以我们将省略它的使用。Android中的应用程序生命周期:
在 Android JVM 中执行前的打包(打包)和安装(安装)应用程序方面,与经典的类 JVM 版本有许多不同之处。该过程可以描述如下:
源码编译:
.java-(javac)->.class-(dexer)->classes.dex;程序集
apk(Android 包):classes.dex+resources files-(aapt)->.apk;签名
apk:.apk-(jarsigner + zipalign)->signed .apk;安装
apk:达尔维克:
classes.dex-(dexopt)->odex(优化的 dex)或quickened dex:Android 运行时 (ART):
classes.dex-(dex2oat)->OAT version of classes.dex(dex+native machine code),即 专有字节码格式被转换为特定于处理器 (CPU) 的机器代码,该处理器 (CPU) 安装在执行安装的设备(例如,移动设备)中。结果放入ELF(Executable and Linkable Format)共享对象中;应用启动:
ActivityManagerService)将应用程序启动命令写入传入命令的套接字;Zygote,其中加载了Android JVM(Dalvik / ART),侦听此套接字并在fork()收到启动应用程序的命令时执行其进程;Zygote出于优化原因预加载核心 Android 库,因此子进程将获得一个预热的VM:Zygote(进程的名称,可以说是提示);forkedELF 共享对象的子进程中(参见上文段落)。请参阅此处、此处和此处了解更多详细信息。
结论:
真希望在研究了经典JVM兼容和Android应用的运行原理之后,你自己已经得出了以下结论(整个答案导致你自己意识到这一点):
.apkAndroid 文件不再包含标准 JVM 可以解释的经典 JVM 字节码(如 HotSpot),而是一些专用于 Android 特定 JVM(Dalvik 和 ART)的字节码 -classes.dex;public static void main(String[] args),其指示必须在中描述META-INF/MANIFEST.MF;AndroidManifest.xml,因此他们“订阅”某些事件(例如,到onCreateinActivity),即 系统是事件驱动的;.apk(见上文),但这将是两个独立的文件,具有不同的内容:META-INF/MANIFEST.MF;AndroidManifest.xml;Dalvik和Android Runtime字节码命令转换为机器码命令的问题native machine code() ,还有台式机(Intel、AMD,即基于x86 和 x64架构的处理器,即CISC):可以在此处找到 Java 与 Android API 比较的简短描述。
更新:StateItPrimitive 的回答提供了对 Java 和 Android 应用程序之间差异的更多技术理解。
不可以,您不能在 Windows 上从 Google Play Market 安装 Java 应用程序。
该问题的作者非常正确地指出,Java 应用程序在设备之间是 100% 可移植的,但来自 Play Market 的 Android 应用程序不能被视为(通常)Java 应用程序。
Android 应用程序要正常工作,除了 Java 虚拟机外,还需要特定的操作系统环境、标准资源文件等等。
如果您查看 Java 应用程序和 Android 应用程序的源代码,这很容易理解。在 Android 应用程序中,您不会找到实际启动应用程序的 main() 函数。Android 应用程序不是由用户启动,而是由操作系统完全控制应用程序的生命周期。在 Android 操作系统之外,为其编写的应用程序无法启动。
但是,虽然这不是提问者的意思,但如果您想在 Windows 上安装应用程序以进行测试(或播放),那么您可以简单地使用模拟器。
Ps 打个比方。我们可以说 Play Market 应用程序是应用程序的一部分。为了使这样的一块成为一个成熟的 Java 应用程序,它必须辅以一定的 Java 代码和资源。这部分存储在 Android 操作系统中(以及针对不同版本和设备制造商的自己的操作系统)。
PPs 我找到了一个解释,其中单词更好javarush。从那里引用
这篇文章已经很过时了,但它传达了主要思想。
不,不幸的是它不会那样工作。应用程序最初是为 Android 编写的。该界面不仅不适用于操作系统 Windows,而且它们根本无法启动。如果你真的需要它,你可以通过模拟器(Bluestacks、Nox...)运行它。
是的,导入和编译都是可能的,但代价是 Java 机器。但是,该程序本身是为 Android 编写的。如果您确定自己是对的,那么如果您现在已经为我回答了这个问题,那么问题的意义何在?