source - Android: javac vs dalvik
project android source (4)
Según tengo entendido, a Google no le gustó la política de licencias de Oracle para usar el JRE en Java ME, por lo que simplemente lo reescribió con su propia especificación JVM que imita al JRE pero se comporta de manera un poco diferente, especialmente cuando se trata de hacer las cosas más eficientes y eficientes. más seguro.
Por lo tanto, si mi entendimiento es correcto, significa que cuando javac
se ejecuta en algún código fuente de Java y se compila en byetcode "binario", un JVM compatible interpretará ese bytecode diferente de Dalvik (en algunos casos). Esta es la diferencia inherente entre Dalvik y otras JVM (compatibles).
Si algo de lo que he dicho hasta ahora es incorrecto, ¡por favor comience a corregirme!
Ahora, si Android viene con su propio compilador (que podría serlo), y compiló la fuente Java de una manera diferente (compatible con Dalvik) que javac
, entonces podría entender cómo no se ejecutaría algún código (no compilado con el SDK de Android) un dispositivo 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
Sin embargo, parece que utilizas javac
para compilar aplicaciones de Android. Así que parece que tenemos esto:
MySource.java --> javac --> MySource.class (JRE-compliant) --> JVM --> running Java app
MySource.java --> javac --> MySource.class (JRE-compliant) --> Dalvik JVM --> running Android app (???)
Si se utiliza javac
para compilar todas las fuentes en el código de bytes, ¿por qué Dalvik no puede ejecutar algunos tipos de código Java?
Ayer hice una pregunta muy similar y, aunque fue respondida técnicamente (después de releer mi pregunta, veo que simplemente no era lo suficientemente específica) nadie pudo explicar qué es lo que es inherente a Dalvik que hace imposible ejecutar el código Java. De proyectos como Google Guice o Apache Camel. Me dijeron que para lograr que Camel se ejecute en Dalvik, que tendría que obtener la fuente de Camel y luego tendría que ser "construido con el SDK de Android", pero no pude aclarar lo que eso significaba o implicaba. .
Con Camel, por ejemplo, tienes esto (simplificado):
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 !!! (???)
Claramente, algo está sucediendo dentro de la JVM de Dalvik que le impide ejecutar ciertos tipos de código Java. Estoy tratando de entender qué tipos de código Java no se ejecutarán cuando se introduzcan en la JVM de Dalvik.
Edición: antes de "¡ pero Camel 3.0 se ejecutará en Android! " Lo sé, ¡no es mi pregunta!
Si algo de lo que he dicho hasta ahora es incorrecto, ¡por favor comience a corregirme!
Ummm, bueno ...
La VM de Dalvik tiene ventajas técnicas sobre la VM de Java para entornos móviles, especialmente el uso agresivo del uso compartido de memoria de copia en escritura, por lo que la VM completa y la biblioteca de clases estándar se comparten entre todos los procesos de la aplicación SDK de Android, lo que reduce la red por proceso. huella de memoria. Vea la respuesta de user370305 (publicada mientras estaba terminando esto) para más información.
El código de
javac
dejavac
se compila de forma cruzada en el código de bytes de Dalvik como parte del proceso de construcción de la aplicación de Android. La máquina virtual Java no puede ejecutar el bytecode Dalvik más de lo que puede ejecutar la salida de/dev/random
; De manera similar, la máquina virtual de Dalvik no puede ejecutar el bytecode de Java.
Aquí hay una publicación de mi blog de hace unos dos años que incluye puntos adicionales.
Si se utiliza javac para compilar todas las fuentes en el código de bytes, ¿por qué Dalvik no puede ejecutar algunos tipos de código Java?
Debido a que la salida de javac
bytes javac
es de compilación cruzada. El compilador cruzado ( dx
) maneja un sabor muy específico de la salida javac
, lo que significa que mientras trabaja con el javac
clásico (lo que habría obtenido de java.sun.com) y OpenJDK para Java 1.5 y 1.6, no funcionará con compiladores alternativos (por ejemplo, GCJ) y, como mínimo, no funcionará con ningún código de bytes nuevo de Java 7.
Nadie pudo explicar qué es lo que es inherente a Dalvik, lo que hace que sea imposible ejecutar el código Java de proyectos como Google Guice o Apache Camel.
Personalmente, nunca he usado Google Guice, aunque Roboguice funciona en Android. Nunca había oído hablar de Apache Camel antes de tu pregunta y estoy bastante confundido al descubrir que no es un puerto Java de Perl. :-)
Cualquier herramienta que realice la generación de bytecode JVM en tiempo de ejecución no funcionará en Android, simplemente porque el compilador cruzado solo está disponible en tiempo de compilación, no en tiempo de ejecución. Además, no estoy familiarizado con las técnicas utilizadas por las herramientas de generación de bytecode JVM en tiempo de ejecución y cómo logran que JVM ejecute ese bytecode, y por lo tanto no sé si existen enganches equivalentes en Android para que Dalvik ejecute fragmentos arbitrarios de Dalvik bytecode.
Sin embargo, dado que se negó a especificar exactamente qué "código Java de proyectos como Google Guice o Apache Camel" está teniendo problemas, y como no estoy muy familiarizado con esos proyectos, es difícil hacer más comentarios.
@alijandro, usted explicó muy bien cómo dalvikvm puede ejecutar el código de byte .dex
y no el código de byte de .dex
. Para el proceso de construcción de la imagen APK de Android que adjuntó, ¿cuáles son las convenciones utilizadas para la codificación de colores y las figuras? ¿Puede por favor adjuntar una referencia?
Esta imagen del documento oficial de Android ilustra el proceso de construcción de Android APK, ayudará a comprender la diferencia entre el código de bytes java y el ejecutable dalvik.
Aquí doy un ejemplo para demostrar algunas de las diferencias.
Hola.java
import java.io.*;
public class Hello {
public static void main(String[] args) {
System.out.println("hello world!!!!");
}
}
use javac
para compilar Hello.java
a java bytecode Hello.class
$ javac Hello.java
Luego use la herramienta dx
de android sdk para convertir el Hello.class
de Hello.dex
Java Hello.class
a Hello.dex
$ $ANDROID_SDK_ROOT/build-tools/21.1.2/dx --dex --output=Hello.dex Hello.class
Después de eso, use adb
para colocar Hello.class
y Hello.dex
en un dispositivo o emulador de Android.
$ adb push Hello.class /data/local/tmp/
$ adb push Hello.dex /data/local/tmp/
use adb shell
para ingresar al entorno de shell del dispositivo Android. Luego use el comando /system/bin/dalvikvm
para ejecutar el sencillo programa java que acabamos de crear Hello.class
y 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!!!!
En el ejemplo anterior, cuando usamos el bytecode Hello.class
java, Hello.class
, error de queja, si cambiamos la clase a dalvik ejecutable Hello.dex
, se ejecutaría correctamente.
I''m trying to understand what types of Java code will not run when "fed" into the Dalvik JVM.
Dalvik JVM se diferencia de otras JVM en los siguientes aspectos:
Utiliza el formato DEX especial para almacenar aplicaciones de binarios frente a los formatos JAR y Pack200 utilizados por las máquinas virtuales Java estándar. Google afirma que DEX da como resultado binarios más pequeños que JAR. Creo que podrían usar Pack200 con el mismo éxito, pero decidieron seguir su propio camino en este aspecto.
Dalvik JVM se optimizó para ejecutar múltiples procesos JVM simultáneamente
Dalvik JVM utiliza arquitectura basada en registros frente a la arquitectura basada en pila de otras JVM con la intención de acelerar la ejecución y reducir los tamaños binarios
Utiliza su propio conjunto de instrucciones (no un bytecode JVM estándar)
Uno puede ejecutar (si es necesario) varias aplicaciones de Android independientes dentro de un solo proceso JVM
La ejecución de la aplicación puede abarcar varios procesos Dalvik JVM "naturalmente". Para apoyar esto agrega:
Mecanismo especial de serialización de objetos basado en parcelas y clases parcelables. Funcionalmente cumple el mismo propósito que el Java Serializable estándar, pero resulta en una huella de datos más pequeña y es potencialmente más indulgente con respecto a las diferencias en las versiones de las clases
Forma especial de Android para ejecutar llamadas entre procesos (IPC) basadas en el lenguaje de definición de interfaz de Android (AIDL)
Hasta que Android 2.2 Dalvik JVM no admitía la compilación JIT, lo que afectó negativamente el rendimiento de la aplicación de Android. Agregarlo en 2.2 mejora notablemente la velocidad de ejecución para aplicaciones de uso frecuente