【问题标题】:NoClassDefFoundError (change class name)NoClassDefFoundError(更改类名)
【发布时间】:2013-07-25 19:51:50
【问题描述】:

我试图通过覆盖 loadClass(String, Boolean) 方法来更改类名。

我正在创建一个 BukkitPlugin。 Bukkitsource 可以找到here

类加载器本身工作正常,我对其进行了测试,所有类都工作正常,在我开始更改类名后开始出现错误。

方法如下:

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;

import org.bukkit.plugin.java.JavaPlugin;

public class PluginClassLoader extends URLClassLoader {

    private final HashMap<String, String> replace;

    public PluginClassLoader(JavaPlugin p, HashMap<String, String> replace) throws Exception {
        super(new URL[0], p.getClass().getClassLoader());
        this.replace = replace;
        File f = null;
        Field file = JavaPlugin.class.getDeclaredField("file");
        file.setAccessible(true);
        f = (File) file.get(p);
        addURL(f.toURI().toURL());
    }

    private final HashMap<String, Class<?>> classes = new HashMap<>();

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        String s = replace.get(name);
        if(s != null)
            name = s;
        Class<?> c;
        try {
            c = findClass(name);
        } catch (Exception e) {
            c = super.loadClass(name);
        }
        return c;
    }




    @Override
    protected Class<?> loadClass(String name, boolean b)
        throws ClassNotFoundException {
        String s = replace.get(name);
        if(s != null)
            name = s;
        Class<?> c;
        try {
            c = findClass(name);
        } catch (ClassNotFoundException e) {
            c = super.loadClass(name, b);
        }
        return c;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        if ((name.startsWith("org.bukkit."))
                || (name.startsWith("net.minecraft."))) {
            throw new ClassNotFoundException(name);
        }

        Class<?> result = classes.get(name);

        if (result == null) {
            result = super.findClass(name);
            classes.put(name, result);
        }
        return result;

    }
}

当我使用类加载器时,每次我使用被替换的类之一时都会得到 NoClassDefFoundError。我最好的猜测是我必须重写另一个方法,但我不知道它可能是什么。

错误日志:

java.lang.NoClassDefFoundError: org/bukkit/craftbukkit/v1_5_R3/CraftServer
at me.leo.itemeffects.IEPlugin.onEnable(IEPlugin.java:25)
at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:457)
at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
at org.bukkit.craftbukkit.v1_6_R2.CraftServer.loadPlugin(CraftServer.java:282)
at org.bukkit.craftbukkit.v1_6_R2.CraftServer.enablePlugins(CraftServer.java:264)
at net.minecraft.server.v1_6_R2.MinecraftServer.l(MinecraftServer.java:313)
at net.minecraft.server.v1_6_R2.MinecraftServer.f(MinecraftServer.java:290)
at net.minecraft.server.v1_6_R2.MinecraftServer.a(MinecraftServer.java:250)
at net.minecraft.server.v1_6_R2.DedicatedServer.init(DedicatedServer.java:151)
at net.minecraft.server.v1_6_R2.MinecraftServer.run(MinecraftServer.java:391)
at net.minecraft.server.v1_6_R2.ThreadServerApplication.run(SourceFile:582)

IEPlugin.java:25 是这样的:

CraftServer server = (CraftServer) Bukkit.getServer();

jvm 正在搜索错误的 classDefinition,它会查找带有包 'v1_5_R3' 的那个,但我将 loadClass() 中的类名替换为 'v1_6_R2'

我将类名 'org.bukkit.craftbukkit.v1_5_R3.CraftServer 替换为 'org.bukkit.craftbukkit.v1_6_R2.CraftServer'

v1_5_R3 的包中的类不存在,所以我在 loadClass(String, Boolean) 方法中将其更改为 v1_6_R2

感谢您的阅读和您希望即将到来的解决方案。

【问题讨论】:

  • 首先,向我们展示您的NoClasDefFoundError。其次,尝试像这样重命名一个类是非常愚蠢的。
  • 请分享错误信息,也不要重写方法,为什么不更改类名 String 然后将其传递给此方法。

标签: java noclassdeffounderror urlclassloader


【解决方案1】:

首先,当你重写一个方法时,它最好写在“@Override”之前。某些程序(例如 Eclipse)会告诉您覆盖是否不正确(如果您忽略了一些覆盖规则)

其次,你的类是受保护的,这意味着它只能在它实现的包中看到。您确定被覆盖的类与这个类在同一个包中吗?这可能是您收到此类错误的原因。

如果您发布更多代码,则更有可能获得帮助。这样,也许有人可以准确地告诉你问题出在哪里。

【讨论】:

    【解决方案2】:

    通常 ClassNotFoundException 表示未找到当前类,NoClassDefFoundError 表示未找到当前加载的类的依赖类(请参阅此stackoverflow thread)。可能您替换的类具有类路径中不存在的依赖项。

    【讨论】:

    • jvm 正在搜索错误的 classDefinition,但整个错误并没有打印在控制台中。错误日志显示了“真正的”原因。
    • 虽然您已将类替换为 v1_6_R2,但类加载器仍然开始加载 v1_5_R3 类。所以,我相信报告的错误仍然是 v1_5_R3。您可能希望将 v1_5_R3 的字节流替换为 v1_6_R2 的字节流,并调用 defineClass 而不是使用新的类名再次重定向到 loadClass。
    • CraftServer类找到并返回无误,返回类后出现错误,打印了loader搜索的class和loader返回的class,serverclass正确返回.这意味着错误不是在 loadclass 中引发的,而是在其他地方引发的。
    猜你喜欢
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    相关资源
    最近更新 更多