我在互联网上找到了OSGi的以下加载器结构。
bootstrap classloader(来自jre / lib / rt.jar的Java标准库 等))^ ^ extension classloader
^^ system classloader(即$ CLASSPATH上的东西,OSGi核心代码)
^(** 从父类加载器限制访问类型的常见OSGi 类加载器:
- | - bundle1的OSGi类加载器 - > (import-package-> classloader的地图)
- | - bundle2的OSGi类加载器 - > (import-package-> classloader的地图)
- | - bundle3的OSGi类加载器 - > (import-package-> classloader的地图)
Here它说
在执行线程上设置上下文类加载器。默认情况下是 始终设置为System classloader或来自新的线程 线程实例已创建。
从上面的结构我们看到系统加载器(=上下文加载器)具有更高的位置,因为我知道父类加载器从不询问它的子代。
所以我的问题请解释当前线程如何与当前包中的类一起工作?
答案 0 :(得分:8)
在OSGi中,线程上下文类加载器(TCCL)是未定义的。你不能指望或断言它将是特别的东西。事实上,很多时候它都是null
。
TCCL是Java 1.2中添加的一个hack,用于支持J2EE。特别是需要支持Entity Beans之类的东西;在现代世界中,它用于支持JPA,JAXB,Hibernate等技术。
父委托的问题在于,虽然底层的应用程序类可以看到父类加载器中所有类的可见性,但不幸的是,父类加载器加载的类不可以看到应用程序类。实际上,这意味着您的应用程序代码可以加载(比方说)构成Hibernate的类,但Hibernate将无法加载您的域类,因为它们位于层次结构中的低于它。
所以,TCCL是发明的。在J2EE应用程序服务器中,TCCL被创建为线程局部变量,并且它具有所有应用程序类的可见性。 Hibernate / JPA / JAXB等可以查询TCCL以查找应用程序类。这在J2EE中很容易实现,因为app服务器控制所有入口点:它控制Web服务器,控制RMI端点,作为应用程序开发人员,您不允许创建自己的线程。
然而,OSGi的编程环境受到的限制要少得多。允许任何bundle创建自己的网络端点,启动自己的线程,或者几乎做任何事情。因此,OSGi没有机会介入并强加一个具有应用程序类可见性的TCCL。此外,“应用程序”的概念是模糊的,因为我们有一个称为模块化的简洁事物。一个应用程序由多个包组成......但是如何定义哪些包可以为TCCL提供类?
所以OSGi基本上就此问题付出了代价。 TCCL未定义,所以你永远不要依赖它。幸运的是,大多数尝试使用的库只是在尝试从中加载类的一系列地方之一。