8

私は現在プラグインシステムを作成しています(私の最初の試み)、私が自分のクラスローダーをつなぎ合わせてディレクトリからプラグインをロードしようとしている他の人々のコードを見てください(これらはクラスファイルになります)

私の問題は、クラスローダーを使用してクラスをロードしようとすると、プログラムを参照するプラグインのインポートがクラスローダーによって検出されないことです。(例:MyClassはプラグインを拡張します。com.mgmc.pluginsnoclassdeffound)別の名前空間?

いくつかのサンプルコード:クラスローダー:

/*


* To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mcgm.game.provider;

import com.mcgm.utils.Misc;
import com.mcgm.utils.Paths;
import java.awt.AWTPermission;
import java.io.*;
import java.net.MalformedURLException;
import java.net.SocketPermission;
import java.net.URL;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.PropertyPermission;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Tom
 */
public class GameClassLoader extends ClassLoader {
private final ProtectionDomain domain;
private final URL base;

public GameClassLoader(final URL url) {
    base = url;
    final CodeSource codeSource = new CodeSource(base, (CodeSigner[]) null);
    domain = new ProtectionDomain(codeSource, getPermissions());
}

public void loadGames() {
    for (File f : Paths.compiledFolder.listFiles()) {
        try {
            Class c = loadClass(f.getPath());
            Misc.outPrint(c.getName());
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(GameClassLoader.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

private Permissions getPermissions() {
    final Permissions ps = new Permissions();
    ps.add(new AWTPermission("accessEventQueue"));
    ps.add(new PropertyPermission("user.home", "read"));
    ps.add(new PropertyPermission("java.vendor", "read"));
    ps.add(new PropertyPermission("java.version", "read"));
    ps.add(new PropertyPermission("os.name", "read"));
    ps.add(new PropertyPermission("os.arch", "read"));
    ps.add(new PropertyPermission("os.version", "read"));
    ps.add(new SocketPermission("*", "resolve"));
    ps.add(new FilePermission(Paths.compiledFolder.getPath(), "read,write,delete"));
    ps.setReadOnly();
    return ps;
}

@Override
@SuppressWarnings("rawtypes")
public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
    Class clazz = findLoadedClass(name);

    if (clazz == null) {
        try {
            byte[] bytes = loadClassData(name);
            clazz = defineClass(name, bytes, 0, bytes.length, domain);
            if (resolve) {
                resolveClass(clazz);
            }
        } catch (final Exception e) {
            clazz = super.loadClass(name, resolve);
        }
    }

    return clazz;
}

public byte[] loadClassData(final String name) {
    try {
        final InputStream in = getResourceAsStream(name.replace('.', '/') + ".class");
        final byte[] buffer = new byte[4096];
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        int n;
        while ((n = in.read(buffer, 0, 4096)) != -1) {
            out.write(buffer, 0, n);
        }
        return out.toByteArray();
    } catch (IOException ex) {
        Logger.getLogger(GameClassLoader.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;

}

@Override
public URL getResource(final String name) {
    try {
        return new URL(base, name);
    } catch (final MalformedURLException e) {
        return null;
    }
}

@Override
public InputStream getResourceAsStream(final String name) {
    try {
        return new URL(base, name).openStream();
    } catch (final IOException e) {
        return null;
    }
}
}

ロードしているプラ​​グイン:(注釈も見つかりません)

import com.mcgm.GameInfo;
import com.mcgm.game.Minigame;
  @GameInfo(name = "RandomGame",
description = "A really long and boring game.",
authors = {"Tom", "Is", "The", "Greatest"},
version = 0.1,
maxPlayers = 100,
teamBased = false,
teamAmount = -1,
PvP = false)
public class game extends Minigame {
}

ロードするクラスを呼び出す方法:

  GameClassLoader classLoader = new GameClassLoader(Paths.compiledFolder.toURI().toURL());
            classLoader.loadClass("game", true);

これは、自分が何をしているのかを知っている人にとっては些細なことだと思います。

4

2 に答える 2

4

最後に!1 日半の検索の後、Vulcan は正しい方向を示してくれました。GameClassLoader を次のように変更しました。

public GameClassLoader(final URL url, ClassLoader parent) {
    super(parent);

そして最後にベースURLを getResourceAsStream() に追加しました

final InputStream in = getResourceAsStream(base.getFile() + "/" + name.replace('.', '/') + ".class");

助けてくれてどうもありがとう!

于 2012-10-19T17:00:29.860 に答える
0

リソース パスに先頭のスラッシュを追加してみてください。 final InputStream in = getResourceAsStream("/" + name.replace('.', '/') + ".class");

これは、 を呼び出すたびに試してみる必要があることですgetResourceAsStream()。私はあなたのためにこれをもう一度試しました。ここでのパスは、 の呼び出しgetResourceAsStream()に使用されるクラスのパッケージに対する相対パスであるため、「ルートから開始」と言うには先頭のスラッシュが必要です。

于 2012-10-19T16:38:37.663 に答える