2012-08-02 24 views
5

सबसे पहले मैंने Load Java-Byte-Code at Runtime देखा है और यह अब तक एक ही स्थान पर पहुंचने में सहायक था, मैं वर्तमान में अटक गया हूं।एंड्रॉइड में बाइट सरणी से कक्षा को कैसे लोड करें?

डिस्क पर फ़ाइल संग्रहीत करने से बचने के लिए मैं एक बाइट सरणी से कक्षा लोड करने की कोशिश कर रहा हूं। इस उदाहरण में परीक्षण के उद्देश्य के लिए मैं बस एक .class फ़ाइल में बाइट सरणी में पढ़ रहा हूं, इसलिए जाहिर है कि फ़ाइल अभी भी डिस्क पर संग्रहीत है, लेकिन यह देखने के लिए है कि कोड काम कर सकता है या नहीं।

मैं इस बाइट सरणी लेता हूं और फिर कक्षा लोड करने के लिए विधि loadClass के साथ एक कस्टम क्लासलोडर का उपयोग करता हूं, लेकिन यह काम नहीं करता है।

byte[] bytearray = null; 
    try{  
    RandomAccessFile f = new RandomAccessFile("/sdcard/ClassToGet.dex", "r"); 
    bytearray = new byte[(int) f.length()]; 
    f.read(bytearray); 

    MyClassLoader classloader = new MyClassLoader(); 
    classloader.setBuffer(bytearray); 
    classloader.loadClass("com.pack.ClassIWant"); 
    } 

यहाँ classloader दिया गया है:

public class MyClassLoader extends DexClassLoader { 

private byte[] buffer; 

    @Override 
    public Class findClass(String className){ 
    byte[] b = getBuffer(); 
    return this.defineClass(className, b, 0, b.length); 
    } 

public void setBuffer(byte[] b){ 
    buffer = b; 
} 
public byte[] getBuffer(){ 
    return buffer; 
} 

और त्रुटि मैं प्राप्त कर रहा है:

java.lang.UnsupportedOperationException: पर वर्ग फ़ाइल के इस प्रकार लोड नहीं कर सकता java.lang.VMClassLoader.defineClass (मूल विधि)

मैंने इसे .class फ़ाइलों, .dex फ़ाइलों, .apk, .jar, आदि के साथ आपूर्ति की है ... मुझे नहीं पता कि व्हा टी "वर्ग फ़ाइल का प्रकार" यह मुझसे चाहता है और उस पर प्रलेखन nonexistent है। कोई मदद महान होगी मैं इस काम को चार दिनों के लिए सीधे प्राप्त करने की कोशिश कर रहा हूं।

+0

http://stackoverflow.com/a/3024261/61855 – theomega

+0

मैं अभी भी भी डेक्स फ़ाइलें/जार फ़ाइलों का उपयोग कर "UnsupportedOperationException" का एक ही त्रुटि संदेश मिल रहा। आपने अपने उदाहरण से क्या किया? – HumanCentipedeLinkedList

+0

आप कौन परेशान कर रहे हैं? मेरे? यदि आप मेरे प्रश्न से जुड़े प्रश्न का संदर्भ देते हैं: मैं इस परियोजना के लिए एंड्रॉइड का उपयोग नहीं कर रहा था, इसलिए वहां कोई समस्या नहीं है। – theomega

उत्तर

1

सुनिश्चित करें कि आपके .dex फ़ाइल है को शामिल करना चाहिए एक वास्तविक dx पर उत्पादन Dalvik निष्पादन योग्य और भेष में नहीं एक जावा .class फ़ाइल। यदि आप .dex एक्सटेंशन का उपयोग करते हैं तो फ़ाइल .dex फ़ाइल होनी चाहिए; अन्यथा एक ज़िप फ़ाइल के लिए .jar एक्सटेंशन का उपयोग करें जिसमें classes.dex प्रविष्टि है।

दलविक के सभी संस्करण स्मृति से कक्षाएं लोड नहीं कर सकते हैं। आप फ़ाइल सिस्टम से कक्षा लोड करके इस के आसपास काम कर सकते हैं। वहाँ DexMaker'sgenerateAndLoad विधि में एक उदाहरण है:

byte[] dex = ... 

    /* 
    * This implementation currently dumps the dex to the filesystem. It 
    * jars the emitted .dex for the benefit of Gingerbread and earlier 
    * devices, which can't load .dex files directly. 
    * 
    * TODO: load the dex from memory where supported. 
    */ 
    File result = File.createTempFile("Generated", ".jar", dexCache); 
    result.deleteOnExit(); 
    JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result)); 
    jarOut.putNextEntry(new JarEntry(DexFormat.DEX_IN_JAR_NAME)); 
    jarOut.write(dex); 
    jarOut.closeEntry(); 
    jarOut.close(); 
    try { 
     return (ClassLoader) Class.forName("dalvik.system.DexClassLoader") 
       .getConstructor(String.class, String.class, String.class, ClassLoader.class) 
       .newInstance(result.getPath(), dexCache.getAbsolutePath(), null, parent); 
    } catch (ClassNotFoundException e) { 
     throw new UnsupportedOperationException("load() requires a Dalvik VM", e); 
    } catch (InvocationTargetException e) { 
     throw new RuntimeException(e.getCause()); 
    } catch (InstantiationException e) { 
     throw new AssertionError(); 
    } catch (NoSuchMethodException e) { 
     throw new AssertionError(); 
    } catch (IllegalAccessException e) { 
     throw new AssertionError(); 
    } 
0

एंड्रॉइड JVM बाइटकोड नहीं चलाता है, लेकिन Dalvik बाइटकोड। तो अपने ऑपरेशन इस लाइन से पहले defineClass()

context.setOptimizationLevel(-1); 
+0

क्या आप इसका उपयोग करने के तरीके के बारे में थोड़ा और विस्तार कर सकते हैं? एक त्वरित Google खोज से देखे जाने वाले एकमात्र उदाहरण राइनो का उपयोग कर रहे हैं जिसका मैं उपयोग नहीं कर रहा हूं। .clex के बजाय पर्याप्त .dex फ़ाइल क्यों लोड नहीं करेगा? – HumanCentipedeLinkedList

+0

मैंने कुछ और में देखा और देखा [यह] (http://stackoverflow.com/questions/3022454/how-to-load-a-java-class- गतिशील-on-android-dalvik) SO पर उत्तर दें। मुझे यकीन है कि यह आपकी मदद करेगा। आपको इसे .dex – tolgap

+0

के रूप में स्टोर करना होगा, मुझे अभी भी "असमर्थितऑपरेशन अपवाद: इस प्रकार की क्लास फ़ाइल लोड नहीं हो सकती" .dex फ़ाइलों के लिए भी एक ही त्रुटि प्राप्त हो रही है। मैंने कोशिश की है .class, .dex, .apk, और .jar और कोई भी काम नहीं। मैं क्या गलत कर रहा हूं? – HumanCentipedeLinkedList

2

मैं एक ही समस्या है कि आप की है।

कारण मुझे त्रुटि मिलती है "इस प्रकार की क्लास फ़ाइल लोड नहीं हो सकती" सरल है।

प्लेटफ़ॉर्म स्रोत में "/dalvik/vm/native/java_lang_VMClassLoader.cpp" जो विधि "defineClass" से संबंधित है, हमेशा निम्नानुसार अपवाद लौटाता है। (संस्करण: आईसीएस)

अंत में, मैं इस निष्कर्ष पर पहुंचा कि मैं बाइट सरणी प्रारूप में .dex लोड नहीं कर सकता।

क्या कोई है जो बाइट सरणी का उपयोग करके .dex लोड कर सकता है? (फ़ाइलों का उपयोग नहीं)

/* 
* static Class defineClass(ClassLoader cl, String name, 
*  byte[] data, int offset, int len) 
*  throws ClassFormatError 
* 
* Convert an array of bytes to a Class object. 
*/ 
static void Dalvik_java_lang_VMClassLoader_defineClass(const u4* args, JValue* pResult) 
{ 
    Object* loader = (Object*) args[0]; 
    StringObject* nameObj = (StringObject*) args[1]; 
    const u1* data = (const u1*) args[2]; 
    int offset = args[3]; 
    int len = args[4]; 
    char* name = NULL; 

    name = dvmCreateCstrFromString(nameObj); 
    ALOGE("ERROR: defineClass(%p, %s, %p, %d, %d)", 
     loader, name, data, offset, len); 
    dvmThrowUnsupportedOperationException(
     "can't load this type of class file"); 

    free(name); 
    RETURN_VOID(); 
} 

/* 
* static Class defineClass(ClassLoader cl, byte[] data, int offset, 
*  int len) 
*  throws ClassFormatError 
* 
* Convert an array of bytes to a Class object. Deprecated version of 
* previous method, lacks name parameter. 
*/ 
static void Dalvik_java_lang_VMClassLoader_defineClass2(const u4* args, JValue* pResult) 
{ 
    Object* loader = (Object*) args[0]; 
    const u1* data = (const u1*) args[1]; 
    int offset = args[2]; 
    int len = args[3]; 

    ALOGE("ERROR: defineClass(%p, %p, %d, %d)", 
     loader, data, offset, len); 
    dvmThrowUnsupportedOperationException(
     "can't load this type of class file"); 

    RETURN_VOID(); 
} 
+0

उस कोड को देखते हुए ऐसा लगता है कि DefineClass ALWAYS असमर्थित ऑपरेशन अपवाद फेंकता है इससे कोई फर्क नहीं पड़ता कि इनपुट क्या है, जो आपने कहा था। अगर ऐसा है तो इसे एपीआई में क्यों अनुमति दें ?? – HumanCentipedeLinkedList

संबंधित मुद्दे