【问题标题】:JBoss 7: how to dynamically load jarsJBoss 7:如何动态加载 jars
【发布时间】:2012-02-01 15:57:31
【问题描述】:

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

【问题讨论】:

  • 您提到 JBoss 7 的依赖项加载已更改。您是否使用早期版本的 JBoss 完成此操作?你能描述一下你以前的方法吗?
  • 我认为this documentation 会有所帮助

标签: java dependencies application-server jboss7.x


【解决方案1】:

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

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,但也许它可以工作......它运行时将数据或 test/data 目录中可用的所有 JAr 文件添加到正在运行的类路径中。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      只是改写问题以确保我正确;

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

      【讨论】:

      • 我喜欢这个答案,但并没有 - 完全 - 解决这个问题。通过 manfiest/jboss-deployment-structure.xml 在 jboss 中设置依赖项之间的最终区别在于,它隐式地使您依赖的所有类在您的应用程序类加载器中可用,而无需显式命名它们或单独加载它们。这样做的好处是确保您将控制权移交给的任何黑盒系统(调度到 jsp 处理程序等)也可以访问这些类(如果它们是使用部署的相同应用程序类加载器启动的)。
      猜你喜欢
      • 1970-01-01
      • 2018-12-14
      • 1970-01-01
      • 2012-07-05
      • 2014-01-29
      • 1970-01-01
      • 2011-09-30
      • 2013-09-06
      • 2013-08-31
      相关资源
      最近更新 更多