2013-07-25 5 views
0

loadClass (String, Boolean) 메서드를 재정 의하여 classname을 변경하려고했습니다.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; 

    } 
} 

을 그리고 난 클래스 로더를 사용할 때 나는 대체 클래스 중 하나를 사용하여 A 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'와 하나 보이지만, 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로 변경하는 이유.

+0

먼저 'NoClasDefFoundError'를 보여주세요. 둘째, 클래스 이름을 변경하려고하면 매우 어리 석다. – tbodt

+0

String 클래스 이름을 변경하지 말고 메서드를 재정의하는 대신 오류 메시지를 공유 한 다음이 메서드에 전달하십시오. –

답변

0

먼저 메서드를 재정의하면 "@Override"앞에 쓰기가 우선됩니다. 이클립스와 같은 일부 프로그램은 오버라이드가 corrent가 아닌지 알려줄 것입니다 (무시 규칙의 일부를 따르지 않는 경우 생략)

둘째, 클래스가 보호됩니다. 즉, 패키지에서만 볼 수 있습니다. 구현됩니다. 오버라이드 된 클래스가이 클래스와 동일한 패키지에 있다고 확신합니까? 어쩌면 당신이 그런 실수를하는 이유 일 수도 있습니다.

코드의 더 큰 부분을 게시하면 도움을받을 가능성이 큽니다. 그런 식으로 누군가가 문제가있는 곳을 정확히 말할 수 있습니다.

+0

코드에 @Override가 있지만 그다지 복사하지 않았습니다. – CoderCloud

0

일반적으로 ClassNotFoundException은 현재 클래스를 찾을 수 없으며 NoClassDefFoundError는 현재로드 된 클래스의 종속 클래스를 찾을 수 없음을 나타냅니다 (이 stackoverflow thread 참조). 아마 당신의 교체 된 클래스는 클래스 패스에 존재하지 않는 의존성을 가지고있을 것이다.

+0

jvm이 잘못된 classDefinition을 검색하지만 콘솔에 전체 오류가 인쇄되지 않습니다. errorloag dosent는 '진짜'원인을 보여줍니다. – CoderCloud

+0

클래스를 v1_6_R2로 바 꾸었지만 classloader는 여전히 v1_5_R3 클래스를로드하기 시작했습니다. 따라서보고 된 오류가 여전히 v1_5_R3이라고 말할 것입니다.v1_5_R3의 바이트 스트림을 v1_6_R2의 바이트 스트림으로 바꾸고 새 클래스 이름으로 loadClass로 다시 리디렉션하는 대신 defineClass를 호출 할 수 있습니다. – Raji

+0

CraftServer 클래스가 발견되어 오류없이 반환됩니다. 클래스가 반환 된 후에 오류가 발생합니다. 로더가 검색하는 클래스와 로더가 반환하는 클래스를 인쇄하고 서버 클래스가 올바르게 반환됩니다. 이는 오류가 loadclass에서 발생하지 않고 다른 곳에서 발생한다는 것을 의미합니다. – CoderCloud

관련 문제