我可以抢先上课吗? [英] Can I pre-empt the class path?

查看:192
本文介绍了我可以抢先上课吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个库是商业产品的插入式扩展。该产品已有几年的历史,并使用Sun的JAXB-2.0库。

I have a library that is a drop-in extension of a commercial product. That product is several years old and uses Sun's JAXB-2.0 libraries.

我的库使用JAXB而且我有一个非常奇怪的错误。 可能导致JAXBElement没有no-arg默认构造函数的内容?

My library uses JAXB and I'm having a very bizarre error. What might cause "JAXBElement Does not have a no-arg default constructor"?

我发现这是由旧库中的错误引起的。我是否可以预先加载已加载的类以强制我的扩展使用该类的正确版本?

I've discovered that this is caused by a bug in the older library. Can I pre-empt the loaded classes to force my extension to use the "right" version of the class?

编辑:随着我的插入我的包装JAXB-2.2.5(在我的插件的类路径中引用)但我怀疑现有的JVM已经加载了该类的2.0版本,引起了我的心痛。

Along with my drop-in I'm packing JAXB-2.2.5 (which is referenced on the classpath of my plugin) but I suspect that the existing JVM has already loaded 2.0 versions of the class, causing my heartache.

推荐答案

每个Java 类加载器。一旦加载了类,就不可能从类加载器中卸载这个类。 删除类的唯一可能性是松开对此类加载器已加载的类的所有实例的所有引用,以及对类加载器本身的引用即可。

Each Java Class is loaded by a ClassLoader. Once a class has been loaded, it is impossible to unload this class from a class loader. The only possibility of getting rid of a class is to loose all references to all instances of classes that this class loader has loaded and to the reference to the classloader itself.

类加载器按层次结构组织。默认情况下,每个类加载器首先要求其父类加载器加载一个类。仅当父类加载器无法加载类时,原始类加载器才会尝试这样做。您可以覆盖此行为以加载JAXB类。

Class loader's are organized in a hierarchy. By default, each class loader first asks its parent class loader to load a class. Only if the parent class loader is unable to load a class, the original class loader will attempt to do so. You could override this behavior in order to load your JAXB classes.

但这并不容易:假设您有一个类 MyObject 加载了类加载器 A 。如果使用类加载器加载相同的类 B ,则为这两个类加载 MyObject.class!= MyObject.class 。这也会导致 MyObject o = getMyObjectFromOtherClassLoader()抛出 ClassCastException

This is not that easy though: Assume you have a class MyObject that was loaded with class loader A. If you load the same class with class loader B then MyObject.class != MyObject.class for the two classes. This would also cause MyObject o = getMyObjectFromOtherClassLoader() to throw a ClassCastException.

Stackoverflow提供一个 child first 类加载器的示例。唯一剩下的就是在类加载器激活之前运行应用程序而不加载类。这个,你可以这样做(未验证的代码):

Stackoverflow provides an example of a child first class loader. The only thing remaining is to run your application without classes being loaded before the class loader gets active. This, you could do as follows (unverified code):

class StartupWrapper {

  public static void main(String[] args) throws Exception {
    Class.forName("com.company.Main", true, 
        new ParentLastURLClassLoader(Arrays.asList(new URL("./new-JAXB.jar"))))
      .getMethod("main", String[].class).invoke(null, args);
  }
}

此包装器将启动您的正常应用程序的 public static void main(String []) com.company.Name 的方法,使用 child-first 首先考虑您的库的类加载器。确保在显式加载之前不加载 com.company.Main 。 (因此反思方法。)

This wrapper would start your normal application's public static void main(String[]) method of the class com.company.Name using the child-first class loader that considers your library first. Make sure that you do not load com.company.Main before your explicit load. (Thus the reflective approach.)

您使用像Maven这样的构建工具吗?你不能明确地排除旧库的依赖吗?遗留应用程序可能会遇到类似新应用程序与旧JAXB类似的问题。

Are you using a build tool like Maven? Can't you explicitly exclude the old library's dependeny? The legacy application will probably have similar problems with the new JAXB as your application has with the old one.

这篇关于我可以抢先上课吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆