In this article, we will talk about the Android runtime environment. Notably, we promise to be brief and explain in short ART and Dalvik (DVM) differences in Android.
在本文中,我们将讨论Android运行时环境。 值得注意的是,我们承诺会简短并简要说明Android中的ART和Dalvik(DVM)差异。
虚拟机 (Virtual Machine)
Let us clear up the difference between JVM and DVM first.
让我们首先弄清JVM和DVM之间的区别。
Java Virtual Machine is a virtual machine capable of executing Java bytecode regardless of the base platform. It is based on the principle “Write once, run anywhere.” The Java bytecode can run on any machine capable of supporting JVM.
Java虚拟机是一种能够在不考虑基础平台的情况下执行Java字节码的虚拟机。 它基于“编写一次,随处运行”的原则。 Java字节码可以在任何支持JVM的机器上运行。
The Java compiler converts .java files into .class files (bytecode). The bytecode is passed to JVM, which compiles it into machine code for execution directly on the CPU.
Java编译器将.java文件转换为.class文件(字节码)。 字节码被传递到JVM,JVM将其编译成机器码,以便直接在CPU上执行。
JVM features:
JVM功能:
- Stack architecture. The stack is used as a data structure where methods are placed and stored. It works by the LIFO scheme or “Last in — First Out.” 堆栈架构。 堆栈用作放置和存储方法的数据结构。 它通过LIFO方案或“后进先出”工作。
Runs .class files only.
仅运行.class文件。
- Uses a JIT compiler. 使用JIT编译器。
Dalvik Virtual Machine (DVM) is a Java virtual machine developed and written by Dan Bornstein and others as part of the Android mobile platform.
Dalvik虚拟机 (DVM)是由Dan Bornstein和其他人开发和编写的Java虚拟机,是Android移动平台的一部分。
We can say that Dalvik is a runtime for Android operating system components and user applications. Each process is executed in its isolated domain. When a user starts an app (or the operating system launches one of its components), the Dalvik virtual machine kernel (Zygote Dalvik VM) creates a separate, secure process in shared memory, where VM is directly deployed as the environment to run the application. In short, Android within looks like a set of Dalvik virtual machines, with executing an app in each.
我们可以说Dalvik是Android操作系统组件和用户应用程序的运行时。 每个进程都在其隔离域中执行。 当用户启动应用程序(或操作系统启动其组件之一)时,Dalvik虚拟机内核(Zygote Dalvik VM)在共享内存中创建一个单独的安全进程,其中VM被直接部署为运行该应用程序的环境。 简而言之,Android内部看起来像一组Dalvik虚拟机,每个虚拟机中都执行一个应用程序。
DVM features:
DVM功能:
- Register-based architecture. The data structure with methods placed there is based on processor registers. Due to POP and PUSH absence, instructions in register VM are executed faster than similar ones in stack VM. 基于寄存器的体系结构。 带有方法的数据结构基于处理器寄存器。 由于缺少POP和PUSH,寄存器VM中的指令比堆栈VM中的相似指令执行得更快。
Executes the bytecode of its format. Android dexer (we’ll talk about it later) converts .class files into .dex format optimized for DVM execution. Unlike a .class file, a .dex file contains several classes at once.
执行其格式的字节码。 Android dexer(我们将在后面讨论)将.class文件转换为针对DVM执行优化的.dex格式。 与.class文件不同, .dex文件一次包含多个类。
If you are interested, you can read more about DVM architecture here.
如果您有兴趣,可以在此处阅读有关DVM架构的更多信息。
Android Dexer (Android Dexer)
A crucial step in creating an APK is converting the Java bytecode to .dex bytecode for Android Runtime and Android developers to know about it. The dex compiler mainly works “undercover” in routine application development, but it directly affects the application build time, .dex file size, and runtime performance.
创建APK的关键步骤是将Java字节码转换为.dex字节码,以供Android Runtime和Android开发人员了解。 dex编译器主要在常规应用程序开发中“秘密执行”,但它直接影响应用程序的构建时间, .dex文件大小和运行时性能。
As already mentioned, the .dex file itself contains several classes at once. Repeating strings and other constants, used in multiple .class files, are included only to save space. Java bytecode is also converted to an alternative command set used by DVM. An uncompressed .dex file is usually a few percent smaller than a compressed Java archive (JAR) from the same .class files.
如前所述,。 dex文件本身一次包含多个类。 在多个.class文件中使用重复字符串和其他常量仅是为了节省空间。 Java字节码也将转换为DVM使用的备用命令集。 未压缩的.dex文件通常比相同的.class文件的压缩Java归档文件(JAR)小百分之几。
Initially, .class files were converted to .dex using the built-in DX compiler. But starting from Android Studio 3.1 onwards, the default compiler was D8. Compared to the DX compiler, the D8 compiles faster and outputs smaller .dex files, providing high application performance during runtime. The resulting bytecode is minified using an open-source utility ProGuard. As a result, we get the same .dex file, but smaller. Then this file is used for APK building and finally for deploying it on the Android device.
最初,使用内置的DX编译器将.class文件转换为.dex 。 但是从Android Studio 3.1开始,默认的编译器是D8 。 与DX编译器相比,D8编译速度更快,并输出较小的.dex文件,从而在运行时提供了较高的应用程序性能。 生成的字节码使用开源实用程序ProGuard最小化 。 结果,我们得到相同的.dex文件,但是更小。 然后,此文件用于APK生成,最后用于在Android设备上部署。
After the D8 in 2018 came R8, which is essentially the same D8, but updated.
在2018年 D8之后出现了R8 ,它与D8基本相同,但已更新。
When working with Android Studio 3.4 and Android Gradle 3.4.0 plugin or higher, Proguard is no longer used for code optimization during compilation. The plugin works by default with R8 instead, which performs code shrinking, optimization, and obfuscation itself. Although R8 offers only a subset of functions provided by Proguard, it allows the converting Java bytecode to dex bytecode to be performed once, further reducing the build time.
当使用Android Studio 3.4和Android Gradle 3.4.0或更高版本的插件时,Proguard不再在编译期间用于代码优化。 默认情况下,该插件与R8配合使用,该插件本身执行代码收缩,优化和混淆。 尽管R8仅提供Proguard提供的功能的子集,但它允许一次将Java字节码转换为dex字节码,从而进一步减少了构建时间。
R8和代码收缩 (R8 and Code Shrinking)
We all know that most applications use third-party libraries such as Guava, Jetpack, Gson, Google Play Services. When we use one of these libraries, often only a small part of each library is used in an application. Without code shrinking, the entire code of the library is stored in your app.
众所周知,大多数应用程序都使用第三方库,例如Guava,Jetpack,Gson,Google Play服务。 当我们使用这些库之一时,通常在应用程序中只使用每个库的一小部分。 在不缩减代码的情况下,库的整个代码都存储在您的应用程序中。
It happens when developers use verbose code to improve readability and maintainability. For example, meaningful variable names and builder pattern can be used to make it easier for others to understand your code. But such patterns usually result in more code than is needed.
当开发人员使用冗长的代码来提高可读性和可维护性时,就会发生这种情况。 例如,有意义的变量名和构建器模式可用于使其他人更容易理解您的代码。 但是这样的模式通常会导致超出所需的代码。
In this case, R8 comes to the rescue. It allows you to significantly reduce the application’s size by optimizing the volume of code actually used by the app.
在这种情况下,R8可以解救。 它允许您通过优化应用程序实际使用的代码量来大幅减少应用程序的大小。
As an example, I will cite figures from the Shrinking Your App with R8 report presented at the Android Dev Summit ‘19:
例如,我将引用在Android Dev Summit '19上发布的“ 使用R8缩小您的应用”报告中的数据:
And below you can see the R8 effectiveness when the beta version was presented (taken from the Android Developers Blog source):
在下面的示例中,您可以看到R8的有效性(摘自Android开发者博客来源):
For detailed information, check the official documentation and the report mentioned above.
有关详细信息,请查看上面提到的官方文档和报告。
Android中的ART vs DVM (ART vs DVM in Android)
DVM was explicitly designed for mobile devices and was used as a virtual machine to run android apps up until Android 4.4 Kitkat.
DVM是专门为移动设备设计的,并用作运行Android应用程序直至Android 4.4 Kitkat的虚拟机。
Starting from this version, ART was introduced as a runtime environment, and in Android 5.0 (Lollipop), ART completely replaced Dalvik.
从此版本开始, ART被引入为运行时环境,在Android 5.0(Lollipop)中,ART完全取代了Dalvik。
The main visible difference between ART and DVM is that ART uses AOT compilation, while DVM — JIT compilation. Not so long ago, ART started using a hybrid of AOT and JIT. We’ll take a look at this a little bit further.
ART和DVM之间的主要可见区别是ART使用AOT编译,而DVM是JIT编译。 不久前,ART开始使用AOT和JIT的混合体。 我们将进一步研究这一点。
DVM
DVM
- Uses JIT Compilation: whenever you start an application, the part of the code necessary for app execution compiles. The rest of the code compiles dynamically. This slows down app launch and operation but reduces the installation time. 使用JIT编译:无论何时启动应用程序,应用程序执行所需的部分代码都会进行编译。 其余代码将动态编译。 这会减慢应用程序的启动和运行速度,但会减少安装时间。
- Speeds up the device’s startup because the application cache is created at runtime. 由于应用程序缓存是在运行时创建的,因此可以加快设备的启动速度。
- DVM apps require less memory than those running on ART. DVM应用程序所需的内存少于ART上运行的内存。
- Reduces battery performance by increasing the CPU load. 通过增加CPU负载来降低电池性能。
- Dalvik is “obsolete” and is not used on Android versions above 4.4. Dalvik是“过时的”,并且不用于4.4以上的Android版本。
ART
艺术
- Uses AOT compilation, i.e., compiles all code during the installation of the app. This speeds up apps running and operation but requires more installation time. 使用AOT编译,即在安装应用程序期间编译所有代码。 这样可以加快应用程序的运行和运行速度,但需要更多的安装时间。
- Slows the device’s startup because the cache is created during the first boot. 由于缓存是在第一次启动时创建的,因此会降低设备的启动速度。
- Due to the AOT compilation approach, requires more memory compared to DVM applications. 由于采用AOT编译方法,因此与DVM应用程序相比需要更多的内存。
- Increases battery performance by reducing CPU operation due to the compilation absence when running applications. 由于运行应用程序时缺少编译,因此可以通过减少CPU操作来提高电池性能。
- Improved Garbage Collection. When using Dalvik, garbage collectors had to perform two heap passes, which resulted in bad UX. In the case of ART, this is not the case: it cleans the heap once for memory consolidation. 改进了垃圾回收。 使用Dalvik时,垃圾收集器必须执行两次堆传递,从而导致不良的UX。 对于ART,情况并非如此:它只清理一次堆以进行内存合并。
JIT + AOT艺术 (JIT + AOT in ART)
Since Android 7, the Android Runtime Environment includes a JIT compiler with code profiling. The JIT compiler complements the AOT compiler, improves runtime performance, saves disk space, and accelerates app and system updates.
从Android 7开始,Android运行时环境包括带有代码配置文件的JIT编译器。 JIT编译器补充了AOT编译器,提高了运行时性能,节省了磁盘空间,并加快了应用程序和系统的更新。
It’s carried out according to the following scheme:
它是按照以下方案执行的:
Instead of running the AOT compilation of each application during the installation, it runs the application under a VM using the JIT compiler (almost the same as in Android < 5.0) but keeping track of pieces of app code executing most often. This information is after used for the AOT compilation of these code fragments. The last operation is performed only during the smartphone is inactive, which is on a charge.
它没有在安装过程中运行每个应用程序的AOT编译,而是使用JIT编译器在VM下运行该应用程序(与Android <5.0几乎相同),但跟踪最常执行的应用程序代码。 此信息用于这些代码片段的AOT编译之后。 仅在智能手机处于非活动状态时(收费),才执行最后一个操作。
Merely speaking, now two different approaches work together, which brings its benefits:
简而言之,现在两种不同的方法协同工作,带来了好处:
- More efficient compilation — when you start an app, the compiler can learn much more about its operation than when performing static analysis, and, as a result, more suitable optimization methods are applied for each situation. 更有效的编译-启动应用程序时,与执行静态分析时相比,编译器可以了解更多有关其操作的信息,因此,每种情况都可以应用更合适的优化方法。
- Preserving RAM and permanent memory — bytecode is more compact than machine code. When we perform AOT compilation only of separate application parts and do not compile applications the user doesn’t use, we can significantly save. NAND-memory space; 保留RAM和永久内存-字节码比机器码更紧凑。 当我们仅对单独的应用程序部分执行AOT编译并且不对用户不使用的应用程序进行编译时,我们可以节省很多时间。 NAND内存空间;
- A sharp increase in installation speed and first boot after system update — no AOT compilation, no delay. 系统更新后,安装速度和首次启动急剧增加-无需AOT编译,没有延迟。
More information about JIT compiler implementation in ART you can find here.
您可以在此处找到有关ART中JIT编译器实现的更多信息。
总结 (Summarizing)
In this article, we have analyzed the main differences between DVM and ART, and generally looked at how Android improved its development tools over time.
在本文中,我们分析了DVM和ART之间的主要区别,并大致研究了Android如何随着时间改进其开发工具。
ART is still under development: new features are being added to improve the experience for both users and developers.
ART仍在开发中:正在添加新功能以改善用户和开发人员的体验。
We hope this article will be helpful for those who are just getting started with Android.
我们希望本文对刚开始使用Android的用户有所帮助。
Originally published at https://www.intexsoft.com on August 3, 2020.
最初于 2020年8月3日 发布在 https://www.intexsoft.com 。
翻译自: https://levelup.gitconnected.com/android-dvm-vs-art-5687c7903e65