检查加载的类是否可以从另一个分配?

时间:2013-08-17 02:07:05

标签: java class reflection classloader

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

那么,有没有解决这个问题?我不想切换类加载器,因为我最初从jar加载,但我希望能够在jar和zip中加载jar。谢谢!

2 个答案:

答案 0 :(得分:2)

您的问题是您错误地使用isAssignableFrom(尽管这是一种非常令人困惑的方法)。这就是你想要的:

ClassLoader.class.isAssignableFrom(cls)

答案 1 :(得分:-2)

我最终搞清楚了各种类型,因为超类(超级接口不同)使用这个: cls.getSuperclass().getName().equals("java.lang.ClassLoader") java.lang.ClassLoader是您需要检查的完全限定名称。您不需要在主类加载器中加载类。