2

所以,我有一个自定义类加载器来将类从字节数组加载到内存中,我遇到了一个问题:当我尝试查看一个类是否可以从另一个(ClassLoader.isAssignableFrom)分配时,它返回 false,即使编译的类扩展或实现它。我假设因为它是由不同的自定义类加载器而不是系统加载的,所以我将如何解决这个问题?我需要这样做的原因是我想检查 jar 文件中的类文件是否是 ClassLoaders 本身,因为我正在为 jar 文件制作 Java 病毒扫描程序。自定义类加载器:

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 返回 false,即使它应该为 true。

那么,有没有办法解决这个问题?我不想切换类加载器,因为我最初是从 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 回答