2013-07-25 86 views
0

我试着通过重写loadClass(String,Boolean)方法来更改类名。NoClassDefFoundError(更改类名称)

我正在创建一个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是寻找错误的类定义,它会寻找一个与包 'v1_5_R3',但我使用'v1_6_R2'替换了loadClass()中类的名称。

我正在用org.bukkit.craftbukkit.v1_6_R2.CraftServer替换classname'org.bukkit.craftbukkit.v1_5_R3.CraftServer “

的包装中v1_5_R3类不存在,那为什么我将其更改为v1_6_R2中的loadClass(字符串,boolean)方法

感谢您的阅读,并为您希望即将召开的解决方案。

+0

首先,让我们看看你的'NoClasDefFoundError'。其次,试图像这样重新命名一个类是非常愚蠢的。 – tbodt

+0

请分享错误消息,而不是重写方法为什么不更改类名称是字符串,然后将其传递给此方法。 –

回答

0

首先,当你重写一个方法时,它被优先写在“@Override”之前。有些程序,比如Eclipse,会告诉你重写是否不正确(如果你忽略了一些压倒一切的规则)

其次,你的类是受保护的,这意味着它只能在包中看到它被执行。你确定被覆盖的类和这个包是在同一个包中吗?这可能是你得到这样一个错误的原因。

如果您发布了大部分代码,它更有可能获得帮助。这样,也许有人能够确切地告诉你问题出在哪里。

+0

我在代码中有@Override,但没有复制它。 – CoderCloud

0

通常,ClassNotFoundException表示未找到当前类,并且NoClassDefFoundError表示未找到当前加载的类的相关类(请参见此stackoverflow thread)。可能你的替换类有一个不存在于类路径中的依赖关系。

+0

jvm正在搜索错误的classDefinition,但整个错误不会打印在控制台中。错误血糖剂量显示“真正的”原因。 – CoderCloud

+0

尽管您已将类替换为v1_6_R2,但类加载器仍然开始加载v1_5_R3类。所以,我相信所报告的错误仍然会说v1_5_R3。您可能需要将v1_5_R3的字节流替换为v1_6_R2的字节流,然后调用defineClass而不是使用新类名重新定向到loadClass。 – Raji

+0

找到并返回CraftServer类时没有错误,返回类后发生错误,我打印了加载程序搜索的类以及加载程序返回的类,并且serverclass正确返回。这意味着错误不是在loadclass中抛出,而是在其他地方抛出。 – CoderCloud