5

最初に、実行時にJava-Byte-Codeをロードするのを見てきましたが、現在行き詰まっているのと同じ場所にたどり着くまでに役立ちました。

ファイルをディスクに保存しないように、バイト配列からクラスをロードしようとしています。この例のテスト目的では、.classファイルをバイト配列に読み込んでいるだけなので、ファイルはまだディスクに保存されていますが、コードが機能するかどうかを確認するだけです。

このバイト配列を取得し、メソッドloadClassでカスタムClassLoaderを使用してクラスをロードしますが、機能しません。

    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などを提供しました...どの「クラスファイルのタイプ」が必要かわかりません。また、そのドキュメントは存在しません。私がこの仕事を4日間続けてやってきたので、どんな助けも素晴らしいでしょう。

4

3 に答える 3

2

私はあなたと同じ問題を抱えています。

「このタイプのクラスファイルを読み込めません」というエラーが表示される理由は単純です。

プラットフォームソースでは、メソッド「defineClass」に関連する「/dalvik/vm/native/java_lang_VMClassLoader.cpp」は常に次のように例外を返します。(バージョン:ICS)

最後に、バイト配列形式で.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();
}
于 2012-08-14T05:30:10.783 に答える
1

ファイルが本物のdxで生成されたDalvik実行可能ファイルであり、偽装され.dexたJavaファイルではないことを確認してください。拡張子.classを使用する場合、ファイルはファイルである必要があります。それ以外の場合は、エントリを含むZIPファイルの拡張子を使用します。.dex.dex.jarclasses.dex

Dalvikのすべてのバージョンがメモリからクラスをロードできるわけではありません。これを回避するには、ファイルシステムからクラスをロードします。DexMakerの generateAndLoadメソッドに例があります:

    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();
    }
于 2012-08-06T21:08:27.050 に答える
0

AndroidはJVMバイトコードを実行しませんが、Dalvikバイトコードを実行します。したがって、操作には前にこの行を含める必要がありますdefineClass()

context.setOptimizationLevel(-1);
于 2012-08-02T21:11:15.900 に答える