【发布时间】:2012-10-10 07:17:07
【问题描述】:
我目前正在创建一个插件系统(我的第一次尝试),查看其他人的代码我试图拼凑我自己的类加载器并从目录中加载插件(这些将是类文件)
我的问题是,每当我尝试使用类加载器加载类时,类加载器都找不到引用该程序的插件中的任何导入。 (ie: MyClass extends Plugin, com.mgmc.plugins noclassdeffound) 不同的命名空间?
一些示例代码: 类加载器:
/*
* 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);
我认为这对于那些知道自己在做什么的人来说是微不足道的!
【问题讨论】:
-
你不是一个负担得起的人。 SO上的人要么在提问,要么在回答问题。太酷了。
-
我很惊讶:你们没有任何包裹吗?我期待 classLoader.loadClass("a.b.c.d.game", true );
-
我试图不添加包,只是因为我希望人们能够添加自己的小游戏 - 我知道这违反了惯例,但这样我就可以拥有所有单个文件夹(或 Jar)中的迷你游戏它最终会扫描文件夹中的所有文件,检查 .class 和 .jar 文件并加载它们(没有包意味着没有扫描子目录)
-
问题是您的 GameClassLoader 没有将系统类加载器作为其父类加载器委托给查找类。 (但我还不确定为什么;仍在研究中。)
-
感谢火神!我已经绞尽脑汁想了一天半,我想别人会知道的!我尝试使用 URLClassLoader 并将父加载器设置为 getSystemClassLoader() 没有运气,但老实说,如果我考虑一下 - 我感觉它根本不会加载资源嗯,也许答案在于写一个父类加载器到我的自定义一个?
标签: java class plugins dynamic classloader