4

我正在尝试使用反射Rod从 jar 文件中加载自定义对象 ()。我已经设法让它找到 jar 文件并扫描类以获取所需的注释,但是每当我调用时,classLoader.loadClass()我都会得到一个ClassNotFoundException我试图加载的类扩展的类。

这是类加载器的代码:

public static Set<Rod> getRods(File rodDirectory) throws Exception {
    rodDirectory.mkdir();
    URLClassLoader classLoader;
    Set<Rod> rods = new HashSet<Rod>();

    for (File f : rodDirectory.listFiles()) {
        if (f.isDirectory() || !f.getName().endsWith(".jar"))
            continue;

        JarFile jar = new JarFile(f);
        Enumeration<JarEntry> e = jar.entries();
        classLoader = URLClassLoader.newInstance(new URL[]{new URL("jar:file:" + f.getAbsolutePath() + "!/")});

        while (e.hasMoreElements()) {
            JarEntry j = (JarEntry) e.nextElement();
            if(j.isDirectory() || !j.getName().endsWith(".class")){
                continue;
            }
            Class<?> c = classLoader.loadClass(j.getName().substring(0, j.getName().length() - 6));
            CustomRod a = c.getAnnotation(CustomRod.class);
            if (a == null)
                continue;
            if (a.minimumVersion() < RodsTwo.getVersion())
                continue;
            rods.add((Rod) c.getConstructor().newInstance());
        }

        jar.close();

    }
    return rods;
}

这是我试图加载的 jar 中的代码:

import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;

import ca.kanoa.RodsTwo.Objects.ConfigOptions;
import ca.kanoa.RodsTwo.Objects.CustomRod;
import ca.kanoa.RodsTwo.Objects.Rod;

@CustomRod(minimumVersion=1.001)
public class Test extends Rod {

    public Test() throws Exception {
        super("Test", 1, 46, new ConfigOptions(), 200);
    }

    @Override
    public boolean run(Player arg0, ConfigurationSection arg1) {
        arg0.sendMessage("HI!");
        return true;
    }



}

我的所有其他代码都可以在这里找到。

我刚刚开始玩反射和任何帮助都很棒!

4

2 回答 2

0

JAR 中可能有自定义子类需要的其他类,但您只选择一个类文件。

例如,假设有人创建AbstractCustomRod然后MyCustomRod扩展它并将它们都放在 JAR 文件中?您的代码将跳过AbstractCustomRod,并且MyCustomRod无法加载。

如果您想指定除了来自 Rod 之外的任何继承,并且 JAR 文件中没有帮助类,那么 JAR 添加的唯一价值是它们可以被签名 - 如果您不关心这一点,您可以很好地接收普通的 .class 文件,这保证它是一个类。

根据您实际在做什么,您可能需要重新考虑这个整体设计 - 这种事情对于父类的更改非常脆弱,并且取决于这些自定义子类的来源,最终运行起来很容易恶意代码。

于 2013-09-16T17:40:12.417 回答
0

OP 代码从 中获取名称JarEntry,剥离".class"并调用ClassLoader.loadClass

ZIP 条目的“名称”是由“/”字符分隔的相对路径(所有平台)。但是,loadClass需要一个用“.”分隔的二进制名称。人物。因此,将名称中的所有“/”字符替换为“.”。

.replace('/', '.')
于 2021-02-02T18:24:55.893 回答