在 Eclipse Equinox 中扩充遗留 OSGi 包的类路径

Augmenting the classpath of legacy OSGi bundles in Eclipse Equinox

我们正在尝试将现有的 Eclipse IDE 产品从 Java 8 迁移到 Java 11。

我们自己的代码一切正常;但不幸的是,该产品还包括一些来自第三方的(相当旧的)捆绑包。这些包已经构建并在 Java 8 下工作并使用 javax.xml.bind (JAXB),我们无法访问源代码,因此我们无法为 Java 11 重建它们。

现在的问题是那些包假定 javax.xml.bind 在(Java 运行时库)类路径中(这对于 Java 8 是正确的),所以他们不在他们的清单中有一个 JAXB 的 Import-Package。当在我们的新 Java 11 产品中执行时,当然,对于 JAXB 类.

,这将在 NoClassDefFoundException 中结束

到目前为止,我的研究得出了两种解决此问题的可能性:

  1. 将 JAXB 添加到 Java 类路径,方法是将其作为模块提供,并在 eclipse.ini.[=18 中添加相应的 --add-modules 参数作为 VM 参数=]

  2. 对于每个遗留包,创建一个包含额外 Import-Package header 的片段,以将 JAXB 导入添加到每个受影响的包。

第一个解决方案对我们来说效果不佳,因为我们自己的包已经在清单中使用 Import-Package header 来利用 JAXB,它在我们的目标平台中作为 OSGi 可用捆。如果我们向 Java 添加一个 JAXB 模块,我们最终会遇到 classes/packages 在两个模块中可用的问题(OSGi 包中未命名的模块,以及我们通过命令行添加的 JAXB)。

第二个解决方案有效,但缺点是我们需要为 N 个遗留包创建 N 个片段,这增加了很多我们的代码库混乱。

所以我的问题是:Equinox 中是否有任何其他机制可用于制作某些包(我们的遗留包)的 BundleClassloader 已知的某些包 (JAXB) without 必须修改或重建这些遗留包?

捆绑包应始终导入 javax.* 个包。那些包总是错的。

您尝试过 boot delegation 并将 JAXB 添加到 Java 类路径吗?

org.osgi.framework.bootdelegation=javax.xml.bind,javax.xml.bind.*

如果已经有一个 bootdelegation 值,您需要将 javax.xml.bind,javax.xml.bind.* 添加到现有值。

由于您还有导入 javax.xml.bind 包的包,因此您还需要确保系统包导出它们。因此,您将需要配置 org.osgi.framework.system.packages.extra 属性 所有 JAXB 包,包括导入所需的版本。

org.osgi.framework.system.packages.extra=javax.xml.bind;version=1.2.3, ...

在搜索 BJ Hargrave's , we ended up finding this blog entry on vogella by Dirk Fauth 中给出的关键字后。该文章中的变体 3 描述了我们成功应用的方式。

简而言之,

  • system.bundle 创建片段并将其设置为 framework 扩展
  • 将您需要的库放在该片段的 class 路径上(或配置 POM 让 Maven 为您完成)
  • 导出你需要导出的包

MANIFEST.MF 片段(节选):

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: JAXB framework extension
Bundle-SymbolicName: net.winklerweb.jaxbfix
Bundle-Version: 1.0.0.qualifier
Fragment-Host: system.bundle; extension:=framework
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ClassPath: lib/jakarta.activation-api-1.2.2.jar,
 lib/jakarta.xml.bind-api-2.3.3.jar,
 lib/jaxb-impl-2.2_1.jar,
 .
Export-Package: com.sun.istack,
 com.sun.istack.localization,
 com.sun.istack.logging,

pom.xml 片段(节选):

<modelVersion>4.0.0</modelVersion>
<groupId>net.winklerweb</groupId>
<artifactId>net.winklerweb.jaxbfix</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>initialize</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <excludeTransitive>false</excludeTransitive>
                        <includeArtifactIds>jakarta.activation-api,jakarta.xml.bind-api,jaxb-impl</includeArtifactIds>
                        <failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
                        <silent>false</silent>
                        <outputDirectory>lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>

    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.eclipse.m2e</groupId>
                <artifactId>lifecycle-mapping</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <lifecycleMappingMetadata>
                        <pluginExecutions>
                            <pluginExecution>
                                <pluginExecutionFilter>
                                    <groupId>org.apache.maven.plugins</groupId>
                                    <artifactId>maven-dependency-plugin</artifactId>
                                    <versionRange>[1.0.0,)</versionRange>
                                    <goals>
                                        <goal>copy-dependencies</goal>
                                    </goals>
                                </pluginExecutionFilter>
                                <action>
                                    <execute>
                                        <runOnIncremental>true</runOnIncremental>
                                        <runOnConfiguration>true</runOnConfiguration>
                                    </execute>
                                </action>
                            </pluginExecution>
                        </pluginExecutions>
                    </lifecycleMappingMetadata>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

<dependencies>
    <dependency>
        <groupId>jakarta.activation</groupId>
        <artifactId>jakarta.activation-api</artifactId>
        <version>1.2.2</version>
    </dependency>
    
    <dependency>
      <groupId>jakarta.xml.bind</groupId>
      <artifactId>jakarta.xml.bind-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    
    <dependency>
      <groupId>org.apache.geronimo.bundles</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>2.2_1</version>
    </dependency>
</dependencies>

最后,一些有用的链接解释了我在研究过程中遇到的 OSGi/Equinox class 加载: