所以,我有一个自定义类加载器来从字节数组中将类加载到内存中,我遇到了一个问题:当我试图查看某个类是否可以从另一个类(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。谢谢!
答案 0 :(得分:2)
您的问题是您错误地使用isAssignableFrom
(尽管这是一种非常令人困惑的方法)。这就是你想要的:
ClassLoader.class.isAssignableFrom(cls)
答案 1 :(得分:-2)
我最终搞清楚了各种类型,因为超类(超级接口不同)使用这个:
cls.getSuperclass().getName().equals("java.lang.ClassLoader")
java.lang.ClassLoader是您需要检查的完全限定名称。您不需要在主类加载器中加载类。