JBoss 7:如何动态加载jar

时间:2012-01-03 16:19:37

标签: java dependencies application-server jboss7.x

我正在使用JBoss 7(此版本中的依赖项加载已更改)。 我的war-application上传到服务器jar并需要使用它们内部的类,但它得到ClassNotFoundException。 所以我找不到一种方法来动态地向模块添加jar依赖项 - MANIFEST.MFjboss-deployment-structure.xml是静态的方法。

3 个答案:

答案 0 :(得分:5)

只需改写问题以确保我正确无误;

您希望能够将任意jar文件上传到服务器,然后使用JVM中包含的类/资源吗?无需重新启动JVM和/或编辑您的配置。

如果是这种情况,那么你应该将jar加载到类加载器中(如果需要,链接当前的类加载器),然后从那里加载类。

假设您将jar文件存储在服务器上,您可以执行以下操作:

public static Class<?> loadClass(String className, String jarFileLocation)
        throws MalformedURLException, ClassNotFoundException {
    URL jarUrl = new File(jarFileLocation).toURI().toURL();
    ClassLoader classLoader = new URLClassLoader(new URL[] {jarUrl }, MyClass.class.getClassLoader());
    return classLoader.loadClass(className);
}

public static Object executeMethodOndClass(String methodName, Class<?>[] parameterTypes, 
                                                Object[] parameters, String className, String jarFileLocation)
        throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException,
        NoSuchMethodException, InvocationTargetException {
    Class<?> loadedClass = loadClass(className, jarFileLocation);
    Method method = loadedClass.getMethod(methodName, parameterTypes);
    Object instance = loadedClass.newInstance();
    return method.invoke(instance, parameters);
}

聚苯乙烯。这是粗略的代码,我甚至没有编译或测试它;它应该工作,但仅此而已,我有可能忽略某些事情或制造错字; - )

PPS。允许上传自定义jar文件,并且执行它的类确实带来了许多(安全)风险。

答案 1 :(得分:0)

关于stackoverflow的@Rage:This question早先可能会给你一些输入如何组织罐子的信息:无论是你自己的罐子还是第三方罐子。

答案 2 :(得分:0)

试试这个(我已经把它抓到了互联网上的某个地方):

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public final class ClassPathHacker {
    private static final Class<?>[] PARAMS = new Class<?>[] { URL.class };
    private static final Logger LOG_CPH = LoggerFactory.getLogger(ClassPathHacker.class);

    private ClassPathHacker() {}

    public static void addFile(final String pFileName) throws IOException {
        final File myFile = new File(pFileName);

        ClassPathHacker.addFile(myFile);
    }

    public static void addFile(final File pFile) throws IOException {
        ClassPathHacker.addURL(pFile.toURI().toURL());
    }

    public static void addURL(final URL pFileUrl) throws IOException {

        /* variables definition */
        final URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        final Class<?> sysClass = URLClassLoader.class;

        try {
            final Method myMethod = sysClass.getDeclaredMethod("addURL", PARAMS);

            myMethod.setAccessible(true);
            myMethod.invoke(sysLoader, new Object[] { pFileUrl });
        } catch (final Exception exc) {
            ClassPathHacker.LOG_CPH.error(exc.getLocalizedMessage(), exc);

            throw new IOException(exc.getLocalizedMessage());
        }
    }
}

与此方法一起:

private static void hackClassPath(final File myData) {
    if (myData.isDirectory()) {

        /* block variables */
        final File[] myList = myData.listFiles();

        /* hacking classpath... */
        for (final File tmp : myList) {
            try {
                ClassPathHacker.addFile(tmp.getAbsolutePath());
                MainApplication.MAIN_LOG.trace("{} added to classpath",
                                               tmp.getAbsolutePath());
            } catch (final IOException iOE) {
                MainApplication.MAIN_LOG.error(iOE.getLocalizedMessage(),
                                               iOE);
            }
        }
    }
}

通过此示例调用:

    MainApplication.hackClassPath(new File("test/data"));
    MainApplication.hackClassPath(new File("data"));

有点hacky,但也许它有效...它运行时将数据或测试/数据目录中可用的所有JAr文件添加到正在运行的类路径中。