Android: javac vs Dalvik

Mi comprensión es que a Google no le gustaba la política de licencias de Oracle para usar el JRE en Java ME, así que lo reescribió usando su propia especificación JVM que imita al JRE pero se comporta un poco diferente, especialmente cuando se trata de hacer las cosas más eficientes y más seguro.

Por lo tanto, si mi comprensión es correcta, significa que cuando javac se ejecuta en algún código fuente de Java y compilado en byetcode "binario", una JVM compatible interpretará que bytecode diferente a Dalvik (en algunos casos). Esta es la diferencia inherente entre Dalvik y otras JVM (compatibles).

Si algo que he dicho hasta ahora es incorrecto, por favor comience por corregirme!

Ahora, si Android viene con su propio compilador (lo que podría), y compilado fuente de Java de una manera diferente (compatible con Dalvik) que javac , entonces podría entender cómo algún código (no compilado con el SDK de Android) no se ejecuta en 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 utiliza 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 javac se utiliza para compilar todas las fuentes en bytecode, entonces ¿por qué es que Dalvik no puede ejecutar algunos tipos de código Java?

Hice una pregunta muy similar ayer y aunque técnicamente se respondió (después de volver a leer mi pregunta veo que simplemente no era lo suficientemente específico) nadie fue capaz de explicar lo que es inherente a Dalvik que hace que sea imposible ejecutar código Java Desde proyectos como Google Guice o Apache Camel. Me dijeron que para conseguir que Camel se ejecutara 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 obtener claridad sobre 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á cuando "alimentado" en la JVM de Dalvik.

Editar: En antes ", pero Camel 3.0 se ejecutará en Android! " Yo sé – no mi pregunta!

 I'm trying to understand what types of Java code will not run when "fed" into the Dalvik JVM. 

La JVM de Dalvik difiere de otras JVMs en los siguientes aspectos:

  • Utiliza formato DEX especial para almacenar binarios de aplicaciones en comparación con los formatos JAR y Pack200 utilizados por las máquinas virtuales Java estándar. Google afirma que los resultados de DEX en 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

  • La JVM de Dalvik fue optimizada para ejecutar simultáneamente varios procesos JVM

  • Dalvik JVM utiliza la arquitectura basada en registros vs. arquitectura basada en pilas de otras JVMs con la intención de acelerar la ejecución y reducir los tamaños binarios

  • Utiliza su propio juego de instrucciones (no un bytecode estándar de JVM)

  • Uno puede ejecutar (si es necesario) varias aplicaciones independientes de Android dentro de un único proceso JVM

  • La ejecución de aplicaciones puede abarcar varios procesos de JVM de Dalvik "naturalmente". Para apoyar esto agrega:

    • Mecanismo de serialización de objetos especiales basado en clases Parcel y Parcelable. Funcionalmente cumple el mismo propósito que el estándar Java Serializable, pero resulta en una huella de datos más pequeña y es potencialmente más indulgente con las diferencias en las versiones de las clases

    • Forma especial de Android para ejecutar llamadas interproceso (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 perjudicaba el rendimiento de las aplicaciones de Android. Añadirlo en 2.2 mejora notablemente la velocidad de ejecución de las aplicaciones que se utilizan con frecuencia

Si algo que he dicho hasta ahora es incorrecto, por favor comience por corregirme!

Ummm, bueno …

  • La VM Dalvik tiene ventajas técnicas sobre la VM Java para entornos móviles, sobre todo el uso agresivo del uso compartido de memoria de copia en escritura, por lo que toda la VM y la biblioteca de clases estándar se comparten entre todos los procesos de la aplicación Android SDK, Huella de la memoria. Vea la respuesta de user370305 (publicada mientras estaba envolviendo esto) para más.

  • El bytecode de javac es compilado en bytecode Dalvik como parte del proceso de construcción de aplicaciones de Android. La VM de Java no puede ejecutar el bytecode de Dalvik más de lo que puede ejecutar la salida de /dev/random ; De forma similar, la VM Dalvik no puede ejecutar bytecode Java.

Aquí hay una entrada de mi blog de hace dos años que entra en puntos adicionales.

Si javac se utiliza para compilar todas las fuentes en bytecode, entonces ¿por qué es que Dalvik no puede ejecutar algunos tipos de código Java?

Debido a que la salida de bytecode javac está compuesta de forma cruzada. El compilador cruzado ( dx ) maneja un sabor muy específico de la salida de javac , lo que significa que mientras trabaja con el clásico javac (lo que habrías conseguido 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 bytecode nuevo de Java 7.

Nadie fue capaz de explicar lo que es inherente a Dalvik que hace que sea imposible ejecutar código Java de proyectos como Google Guice o Apache Camel

Personalmente, nunca he utilizado Google Guice, aunque Roboguice funciona en Android. Nunca había oído hablar de Apache Camel antes de su pregunta y estoy bastante confundido para encontrar que no es un puerto Java de Perl. Todos los derechos reservados

Cualquier herramienta que ejecute generación de bytecode JVM no funcionará en Android, simplemente porque el compilador cruzado sólo 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 de ejecución y cómo obtienen la JVM para ejecutar ese bytecode y, por lo tanto, no sé si existen ganchos equivalentes en Android para que Dalvik ejecute bloques arbitrarios de bytecode Dalvik.

Sin embargo, ya que no quiso 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 comentar más.

Esta imagen de Android documento oficial ilustran el proceso de construcción de Android APK, que ayudará a entender la diferencia entre java bytecode y dalvik ejecutable. Introduzca aquí la descripción de la imagen

Aquí les doy un ejemplo para demostrar algunas de las diferencias.

Hola jajaja

 import java.io.*; public class Hello { public static void main(String[] args) { System.out.println("hello world!!!!"); } } 

Utilizar javac para compilar Hello.java a java bytecode Hello.class

 $ javac Hello.java 

A continuación, utilice la herramienta dx de android sdk convertir java bytecode 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 poner Hello.class y Hello.dex en un dispositivo o emulador Android.

 $ adb push Hello.class /data/local/tmp/ $ adb push Hello.dex /data/local/tmp/ 

adb shell para ingresar al entorno de shell del dispositivo Android. A continuación, utilice el comando /system/bin/dalvikvm para ejecutar el programa java simple 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 de Java Hello.class , dalvikvm error de queja, si cambiamos la clase a dalvik ejecutable Hello.dex , se ejecutaría correctamente.

  • La notificación de Android vuelve a la actividad incorrecta
  • Mensaje de notificación de AudioTrack corriente
  • Android Studio: ¿Cómo excluir el módulo google-services en el sabor del producto?
  • ¿Cómo leer y escribir UTF-8 al disco en el Android?
  • Cómo llamar a la función de la actividad principal de ArrayAdapter personalizado?
  • Crear un controlador personalizado de finalización / devolución de llamada para devolver objetos después de que se completa una solicitud HTTP
  • Mostrar HTML con formato de cadena
  • Mostrar el valor cuando se pulsa
  • Android Studio 2.2.0.12 diseñador automáticamente anuncios "@ + id" prefijo antes de la identificación de la vista y que causa este error inusual
  • Obteniendo una imagen mediana de la secuencia de imágenes con OpenCV
  • El tamaño de imagen de Android cambia después de la devolución de llamada de la cámara
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.