2010-06-11 19 views
30

Me pregunto si y cómo se puede cargar archivos DEX o de clase dinámicamente en Dalvik, alguna función de prueba quick'n'dirty que escribí fue la siguiente:¿Cómo cargar una clase Java dinámicamente en android/dalvik?

public void testLoader() { 
      InputStream in; 
      int len; 
      byte[] data = new byte[2048]; 
      try { 
        in = context.getAssets().open("f.dex"); 
        len = in.read(data); 
        in.close(); 
        DexFile d; 
        Class c = defineClass("net.webvm.FooImpl", data, 0, len); 
        Foo foo = (Foo)c.newInstance(); 
      } catch (IOException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
      } catch (IllegalAccessException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } catch (InstantiationException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
      } 
    } 

mientras que la interfaz es Foo este

public interface Foo { 
      int get42(); 
    } 

y f.dex contiene alguna implementación dx'ed de esa interfaz:

public class FooImpl implements Foo { 
      public int get42() { 
        return 42; 
      } 
    } 

El piloto de pruebas anterior arroja a defineCl culo() y no trabajo y yo investigamos el código Dalvik y encontramos este:

http://www.google.com/codesearch/p?hl=en#atE6BTe41-M/vm/Jni.c&q=Jni.c ...

Así que me pregunto si alguien me puede iluminar si esto es posible en alguna otra manera o no se supone que sea posible. Si no es posible, ¿alguien puede explicar por qué esto no es posible?

+1

Tiene 'DexFile d', luego nunca lo asigne ni lo use. AFAIK, 'DexClassLoader' es el enfoque correcto, aunque no lo he usado personalmente. – CommonsWare

+0

Eso es cierto, el DexFile es un resto de otro truco sucio que probé, ahora investigaré DexClassLoader. – anselm

+0

Intenté usar DexClassLoader, pero eso tampoco funciona. Creé una clase derivada y llamé al superconstructor con super ("/ sdcard/f.jar", "/ sdcard", null, getSystemClassLoader()); Pero no tuvo éxito. Ya sea que defineClass o findClass devuelva cualquier clase que esté asociada dinámicamente. Mi sospecha es que Android no es compatible con esto en absoluto, de lo contrario normal defineClass debería funcionar ya. Probablemente debido a algunos problemas de seguridad. Pero definitivamente me gustaría escuchar las razones, también comencé un hilo en el grupo de Google android-developers. – anselm

Respuesta

47

Hay un example de DexClassLoader en el conjunto de pruebas Dalvik. Accede el cargador de clases reflexivamente, pero si usted está construyendo contra el SDK de Android que sólo se puede hacer esto:

String jarFile = "path/to/jarfile.jar"; 
DexClassLoader classLoader = new DexClassLoader(
    jarFile, "/tmp", null, getClass().getClassLoader()); 
Class<?> myClass = classLoader.loadClass("MyClass"); 

Para que esto funcione, el archivo jar debe contener una entrada llamada classes.dex. Puede crear dicho jar con la herramienta dx que se envía con su SDK.

+2

Reemplace "/ tmp" con algo más en el dispositivo. – fadden

+0

Gracias, puedo confirmar que esto funciona ahora, ¡genial! – anselm

+2

dx.bat --dex --output = E: \ classes.dex E: \ test_app.jar – diyism

Cuestiones relacionadas