4

クラスローディングの概念に頭を悩ませている問題があります。プログラミングを始めてしばらく経ちましたが、クラスローディングがどのように機能するかについては比較的よく知っています。いくつかの例を見て、詳細を読みました。クラスローディングとクラス自体の背後にありますが、ある程度は理解していますが、私を逃れ、検索しやすい用語に入れるのはかなり難しいように思われる概念があります。

基本的に、私はMinecraft用に開発しているゲームモード用の「ギルド」を作成しようとしています。これらのギルドは独自のクラスにあり、起動時またはメソッド「reloadGuildFiles()」が発行されるたびにゲームに読み込まれます。これらのクラスを開発するには、最初にメインアプリケーションをエクスポートし、作成中のギルドのクラスパスとメインアプリケーションの依存関係に追加します。

これが「reloadGuildFiles」メソッドです。

public void reloadGuildFiles() {
  unloadGuildFiles();

  synchronized ( _sync ) {
   System.out.println( "Loading guild class files." );

   File guildDataSourceDirectory = new File( "Prospect/Guilds/" );

   URLClassLoader urlcl = null;

   try {
    urlcl = URLClassLoader.newInstance( new URL[] { guildDataSourceDirectory.toURI().toURL() }, Thread.currentThread().getContextClassLoader() );
   } catch ( Exception e ) {
    e.printStackTrace();
    return;
   }

   if ( urlcl == null )
    return;

   for ( File guildDataFile : guildDataSourceDirectory.listFiles() ) {
    if ( !guildDataFile.getName().endsWith( ".class" ) ) {
     System.out.println( "Skipping " + guildDataFile.getName() );
     continue;
    }

    try {
     String className = guildDataFile.getName().substring( 0, guildDataFile.getName().lastIndexOf( "." ) );

     System.out.println( "Loading: " + className + "\n" +
       "\tfrom: " + guildDataFile.getPath() );

     Class<?> clazz = urlcl.loadClass( className );

     Object object = clazz.newInstance();

     if ( object instanceof Guild == false ) {
      System.out.println( "Object loaded is not an instance of Guild." );
      continue;
     }

     Guild guild = ( Guild ) object;

     if ( _guildMap.containsKey( guild.getName() ) ) {
      System.out.println( "Duplicate guild names in guild map: " + guild.getName() );
      continue;
     }

     _guildMap.put( guild.getName(), guild );
     guild.onGuildLoaded();
    } catch ( Exception e ) {
     System.out.println( e.getMessage() );
     e.printStackTrace();
     continue;
    }
   }
  }
 }
}

これがメインアプリケーションに含まれるGuildクラスです。

public abstract class Guild {
 public abstract String getName();

 public void onGuildLoaded() {
  System.out.println( "Loaded: " + getName() );
 }
}

これが私がクラスロードしようとしているクラスです

public class Warrior extends Guild {
 public String getName() {
  returns "Warrior";
 }
}

これが私に与えているエラーです:

java.lang.NoClassDefFoundError: Guild
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(Unknown Source)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$000(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.net.FactoryURLClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at GuildManager.reloadGuildFiles(GuildManager.java:53)
        at Prospect.enable(Prospect.java:64)
        at PluginLoader.load(PluginLoader.java:205)
        at PluginLoader.reloadPlugin(PluginLoader.java:189)
        at je.d(je.java:1196)
        at je.a(je.java:430)
        at bg.a(SourceFile:24)
        at bh.a(SourceFile:218)
        at je.a(je.java:56)
        at dp.a(SourceFile:85)
        at net.minecraft.server.MinecraftServer.h(SourceFile:267)
        at net.minecraft.server.MinecraftServer.run(SourceFile:208)
        at bw.run(SourceFile:482)
Caused by: java.lang.ClassNotFoundException: Guild
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.net.FactoryURLClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 25 more

私が収集できることと私が理解していることから、メインアプリケーションがロードされるクラスのビルドパス上にある場合でも、クラスローダーはクラスギルドを認識しません。クラスローダーにメインアプリケーションに含まれているGuildクラスを認識させる必要があると思いますが、これを行う方法はありますか、それとも明らかに間違っていることがありますか?

4

1 に答える 1

1

ここで確認できる唯一の問題はThread.currentThread().getContextClassLoader()、何らかの理由でクラスへのアクセスに使用できないクラスローダーが生成されることですGuild

代わりにこれを試してください:

urlcl = URLClassLoader.newInstance( new URL[] { guildDataSourceDirectory.toURI().toURL() }, Guild.class.getClassLoader()); 
于 2010-11-24T12:38:46.787 に答える