JBoss 7:如何动态加载 jar

发布于 2024-12-25 01:47:08 字数 189 浏览 2 评论 0原文

我正在使用 JBoss 7(此版本中的依赖项加载已更改)。 我的战争应用程序上传到服务器 jar 并需要使用其中的类,但它得到了 ClassNotFoundException。 所以我找不到动态向模块添加 jar 依赖项的方法 - MANIFEST.MF、jboss-deployment-struct.xml 是执行此操作的静态方法。

I am using JBoss 7 (dependency loading was changed in this version).
My war-application uploads to server jars and need to use classes inside of them, but it gets ClassNotFoundException.
So I can't find a way to add jar-dependencies to modules dynamically - MANIFEST.MF, jboss-deployment-structure.xml are static way of doing this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猛虎独行 2025-01-01 01:47:08

只是重新表述问题以确保我的回答正确;

您希望能够将任意 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 文件并执行其中的类确实会带来许多(安全)风险。

Just rephrasing the question to make sure I it correctly;

You want to be able to upload an arbitrary jar file to the server and then use the contained classes/resources in the JVM? Without restarting the JVM and/or editing your configuration ofcourse.

If that's the case, then you should load the jar into a classloader (chaining your current classloader if needed) and then load the class from there.

Assuming you store the jar-file physically on the server you could for example do something like:

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);
}

Ps. this is crude code, I didn't even compile or test it; it should work, but nothing more then that and there is the chance I overlooked something or made a typo ;-)

Pps. allowing custom jar files to be uploaded and classes from it to be executed does bring a number of (security) risks with it.

那一片橙海, 2025-01-01 01:47:08

@Rage:这个问题 之前询问的 stackoverflow 可能会为您提供一些如何组织 jar 的信息:无论是您自己的 jar 还是第三方 jar。

@Rage: This question on stackoverflow asked earlier might give you some inputs how to organize jars: be it your own or third-party jars.

伤感在游骋 2025-01-01 01:47:08

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

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 文件目录到正在运行的类路径。

Try this (I've grabbed it somewhere on the Internet):

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());
        }
    }
}

Together with this method:

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);
            }
        }
    }
}

And with this sample call:

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

A bit hacky, but maybe it works... it runtime adds all JAr files available in the data or test/data directory to the running classpath.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文