2

そのため、バイト配列からクラスをメモリにロードするカスタム クラスローダーがあり、問題があります。クラスが別のクラスから割り当て可能かどうかを確認しようとすると (ClassLoader.isAssignableFrom)、コンパイルされたクラスが拡張されていても、false が返されます。またはそれを実装します。システムのクラスローダーではなく、別のカスタムクラスローダーによってロードされているためだと思いますが、どうすればこれを修正できますか? これを行う必要があるのは、jar ファイル用の Java ウイルス スキャナーを作成しているため、jar ファイル内のクラス ファイルが ClassLoader 自体であるかどうかを確認したいからです。カスタムクラスローダー:

public class CL extends ClassLoader {

byte[] jar = null;

private HashMap<String, Class<?>> classes = new HashMap<String, Class<?>>();
private HashMap<String, byte[]> resources = new HashMap<String, byte[]>();

public CL(byte[] jar) {
    this.jar = jar;
}

private JarInputStream getStream() {
    try {
        return new JarInputStream(new ByteArrayInputStream(jar));
    }catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public InputStream getResourceAsStream(String name) {
    if (!resources.containsKey(name)) {
        try {
            JarInputStream stream = getStream();
            JarEntry entry = stream.getNextJarEntry();
            ArrayList<JarEntry> ent = new ArrayList<JarEntry>();
            while (entry != null) {
                String en = entry.getName().replace("/", ".");
                if (en.contains(".")) {
                    en = en.substring(0, en.lastIndexOf("."));
                }
                if (en.equals(name)) {
                    break;
                }
                ent.add(entry);
                entry = stream.getNextJarEntry();
            }
            if (entry == null) {
                for (JarEntry e : ent) {
                    String en = e.getName().replace("/", ".");
                    if (en.contains(".")) {
                        en = en.substring(0, en.lastIndexOf("."));
                    }
                    if (en.lastIndexOf(".") > 0 && en.substring(en.lastIndexOf(".") + 1).equals(name)) {
                        entry = e;
                        break;
                    }
                }
            }
            if (entry == null) {
                return null;
            }
            ent = null;
            ByteArrayOutputStream byt = new ByteArrayOutputStream();
            while (true) {
                int r = stream.read();
                if (r < 0) break;
                byt.write(r);
            }
            stream.close();
            byte[] reqc = byt.toByteArray();
            return new ByteArrayInputStream(reqc);
        }catch (IOException e) {
            e.printStackTrace();
        }
    }else {
        return new ByteArrayInputStream(resources.get(name));
    }
    return null;
}

public Class<?> findClass(String name) {
    if (!classes.containsKey(name)) {
        try {
            JarInputStream stream = getStream();
            JarEntry entry = stream.getNextJarEntry();
            while (entry != null) {
                String en = entry.getName().replace("/", ".");
                if (en.contains(".")) {
                    en = en.substring(0, en.lastIndexOf("."));
                }
                if (en.equals(name)) {
                    break;
                }
                entry = stream.getNextJarEntry();
            }
            if (entry == null) {
                return null;
            }
            ByteArrayOutputStream byt = new ByteArrayOutputStream();
            while (true) {
                int r = stream.read();
                if (r < 0) break;
                byt.write(r);
            }
            stream.close();
            byte[] reqc = byt.toByteArray();
            Class<?> c = defineClass(name, reqc, 0, reqc.length, CL.class.getProtectionDomain());
            classes.put(name, c);
            return c;
        }catch (IOException e) {
            e.printStackTrace();
        }
    }else {
        return classes.get(name);
    }
    return null;
}
}

何かがクラスローダーから割り当て可能かどうかを確認するための私のコード(clは私のクラスローダーのインスタンスです):

                                    Class<?> cls = cl.findClass(fname);
                boolean isCL = false;
                if (cls.isAssignableFrom(ClassLoader.class)) {
                    isCL = true;
                }
                boolean bCL = false;
                for (Method m : cls.getMethods()) {
                    String mn = m.getName();
                    if (isCL) {
                        if (mn.contains("loadClass") || mn.contains("defineClass") || mn.contains("findClass")) {
                            bCL = true;
                        }
                    }
                }

問題: isAssignableFrom が true であるべき場合でも、false を返します。

それで、これに対する修正はありますか?最初はjarからロードしているので、クラスローダーを切り替えたくありませんが、jarとzipの中にjarをロードできるようにしたいと考えています。ありがとう!

4

2 に答える 2

2

あなたの問題は、あなたがisAssignableFrom間違って使用していることです (とはいえ、非常に紛らわしい方法です)。これはあなたが望むものです:

ClassLoader.class.isAssignableFrom(cls)
于 2013-08-17T02:58:46.617 に答える
-2

スーパークラス(スーパーインターフェイスは異なります)については、これを使用して、ある種のハックを考え出すことになりました: cls.getSuperclass().getName().equals("java.lang.ClassLoader")java.lang.ClassLoader は、確認する必要がある完全修飾名です。メインのクラスローダーにクラスをロードする必要はありません。

于 2013-08-17T02:54:23.740 に答える