【发布时间】: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