【问题标题】:Dangers of using reflection to add files to classpath at runtime在运行时使用反射将文件添加到类路径的危险
【发布时间】:2012-10-27 17:47:10
【问题描述】:

最近我一直在寻找在运行时将 jar 文件动态加载到我的应用程序中的方法。

我已经多次提出某个解决方案,这基本上是一个“hack”,它获取系统类加载器并使用反射来访问受保护的 addURL 方法,以便在运行时将其他文件添加到原始类路径。这个解决方案据说效果很好,并且避免了编写和使用自制自定义类加载器时出现的问题。

看起来像这样:

URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;

try {
      Method method = sysclass.getDeclaredMethod("addURL", parameters);
      method.setAccessible(true);
      method.invoke(sysloader, new Object[] { u });
 } catch (Throwable t) {
      t.printStackTrace();
      throw new IOException("Error, could not add URL to system classloader");
 }

我的问题如下:我认为首先使 addURL 方法受到保护是有充分理由的,当动态地将文件添加到类路径时肯定存在某种陷阱或危险。

除了假设系统类加载器总是一个URLClassLoader,“应该总是这样”(TM),使用这个“hack”时我会遇到什么样的麻烦?

谢谢

【问题讨论】:

  • 为什么要更改 system 类加载器而不是创建一个知道额外 jar 文件的新类加载器实例?
  • 我不完全确定要诚实。一般来说,我对类加载器的概念非常陌生,所以我仍然有很多关于它们的地方我不完全理解。我在stackoverflow上的其他地方读到,使用自定义类加载器可能会在某些情况下导致问题,例如,如果我使用它来加载已在程序启动时通过默认类路径加载的库。上面的这个“hack”,尽管它很讨厌,但被认为是在运行时加载 jar 的唯一方法,而不会有遇到依赖/不兼容问题的风险。
  • 那么您是在 尝试 加载已经在默认类路径中的库吗?这种 hack 听起来比使用单独的类加载器的设计方法风险更大。
  • 我正在尝试加载使用(某些)与我的主程序相同的库的插件。我理解它的方式是这样的:如果我使用这个hack,在程序启动时已经在类路径上的库在运行时不会再次加载(因为类加载器足够智能,不会这样做),因此会有没有问题。但是,如果我使用自定义类加载器,该库将被加载两次(一次在启动时使用系统类加载器,一次在运行时使用我的自定义类加载器),这可能会导致问题。
  • 我会强烈建议您隔离事物。可能将您的主程序加载到一个类加载器中,并将每个插件加载到一个单独的类加载器中。这样,一个插件中的库的任何滥用都不会影响其他插件或您的程序。这是设计的工作。但是,您似乎决心以不受支持的方式继续前进,我怀疑我无法说服您。祝你好运...

标签: java reflection classloader


【解决方案1】:

主要的危险是您依赖运行时检查方法的存在。

如果将来方法签名发生变化,您将在运行时才知道它。如果没有提供替代方法,这也可能会导致糟糕的情况。

此外,正如巨大的已经指出的那样,设计者选择制作方法protected 是有原因的(除了缺乏远见)

【讨论】:

    猜你喜欢
    • 2013-08-05
    • 2010-11-03
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 2012-02-23
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多