隔离开放式源代码软件包
您可以使用多种方法从开放式源代码软件 (OSS) 包中隔离 Java™ Platform, Enterprise Edition (Java EE) 应用程序和其他 Java EE 可部署工件。 应用这些方法来解决使用 WebSphere® Application Server 随附的 OSS 包时可能发生的类装入错误和意外运行时行为。
开放式源代码软件 API 主题列出了 WebSphere Application Server 提供的旨在用于定向应用程序的 OSS 软件包,并提供了对有关其使用的文档的引用。
如果 Java EE 应用程序迂到旨在直接供应用程序使用的 OSS 包的问题,请参阅相应的使用情况文档以验证是否正确配置了应用程序和服务器。 例如,如果应用程序迂到涉及 Apache Commons 日志记录的类装入问题,请参阅 Jakarta Commons Logging 主题。
当应用程序迂到 OSS 软件包不用于直接应用程序的问题时,请参阅本主题中包含的 用于将 Java EE 应用程序与 OSS 软件包隔离的最佳实践 部分,以了解在链接到 WebSphere Application Server提供的相同软件包时如何保护为应用程序提供的 OSS 软件包。
用于隔离其他 Java EE 工件的方法较少。 独立资源适配器和资源提供程序具有一个用来启用隔离的配置选项。 对于迂到 WebSphere Application Server随附的 OSS 软件包问题的独立资源,请参阅 隔离资源提供程序的注意事项 主题以确定隔离资源是否可行。 如果是这样,请设置该选项。 重新启动服务器时,运行时将使用使用 parent_last 授权和资源类路径配置的单独类装入器来装入资源。
如果资源隔离不可行,或者发生故障的 Java EE 工件不是资源,请使用本文档的 配置始终受保护 (隔离) 的包 部分中描述的方法将工件与有问题的 OSS 包隔离。
将 Java EE 应用程序与 OSS 包隔离的最佳实践
使用共享库, parent_last 类装入器授权,或者在必要时使用始终受保护的包,以保护应用程序免受 WebSphere Application Server随附的 OSS 包的保护。
隔离的共享库
将应用程序与 WebSphere Application Server 随附的 OSS 包隔离的理想方法是将该包部署为隔离的共享库,并将其与所有从属应用程序和 Web 应用程序归档 (WAR) 模块相关联。 这种方法只允许与该库相关联的应用程序和 WAR 模块使用 OSS 软件包。 在运行时,已隔离共享库的类会从它们自己的类装入器实例装入,以确保库装入器立即装入 OSS 类,并且这些库类会定义用来共享该库的所有应用程序。
myAppCL) 的授权方式设置为 Classes
loaded with the parent class loader first (Parent_first)时,方法 myAppCL.loadClass(clsName) 按以下顺序查找 clsName :- 在 JVM 类高速缓存中搜索已定义的类
<myAppCL, clsName> - 搜索
clsName的每个关联的隔离库类装入器的类路径 - 将
loadClass(clsName)委派给myAppCL的父类装入器 - 在
myAppCL的类路径中搜索clsName
myAppCL.loadClass(clsName) 将按以下顺序查找 clsName :- 在 JVM 类高速缓存中搜索已定义的类
<myAppCL, clsName> - 在
myAppCL的类路径中搜索clsName - 搜索
clsName的每个关联的隔离库类装入器的类路径 - 将
loadClass(clsName)委派给myAppCL的父类装入器
因为始终会在模块类装入器委派给父代之前搜索相关联的共享库,所以无论 myAppCL 配置为 Parent_first 还是 Parent_last,该方法都有效。
服务器共享库
将 OSS 软件包与应用程序隔离的另一种方法是,将共享库与服务器配置中定义的类装入器相关联。 服务器定义的类装入器的授权方式必须设置为 Parent_last。 此方法不如使用隔离共享库,因为所有应用程序和 WAR 模块类装入器都必须将 loadClass() 委派给至少一个父代以装入库中的类。
有关如何创建和配置共享库的信息,请参阅 管理共享库 主题。
类装入器授权
当共享库不可行时,将 OSS 软件包作为相依 JAR 组合到应用程序内。 安装应用程序后,针对装入 OSS 软件包的每个应用程序和 WAR 模块类装入器,将类装入 (授权) 方式设置为 Parent_last 。 与使用已隔离共享库相比,此方法欠佳,因为当已隔离共享库类装入器定义某个类以及 JVM 装入使用相同类装入器的相依类时,在任何其他应用程序、WAR 模块或服务器定义的类装入器上找不到相依类。
类装入 主题描述如何设置应用程序和 WAR 模块类装入器的授权方式。
如果上述方法都不可行,请尝试 配置始终受保护 (隔离) 的包 ,如下一节所述。
配置始终受保护(隔离)的软件包
WebSphere Application Server 维护其从 WebSphere Application Server 类装入器层次结构中 OSGi 网关下的所有类装入器隐藏的 始终受保护的 (或 隔离的) 包名的列表。 配置始终受保护的包,以将所有 Java EE 部署的工件与 WebSphere Application Server随附的 OSS 包隔离。
始终受保护的包控制 WebSphere Extensions 类装入器 (ExtClassLoader) (应用程序和共享库类装入器的逻辑父代) 是否将装入操作委派给 OSGi 网关。 由于 OSGi 网关使 OSS 包可视,因此阻止对网关的授权可有效阻止 Java EE 应用程序和共享库意外地链接到声明为始终受保护的 OSS 包。 此功能还支持直接从 ExtClassLoader 类路径装入的已部署工件,包括配置为非隔离,定制服务和定制认证模块的独立资源适配器和提供程序。
使用始终受保护的软件包时,不能指定干扰 WebSphere Application Server 功能的软件包。 禁止的软件包包括 {"java.", "com.", "com.ibm."}。 虽然不太可能,但您仍可能还会配置始终受保护的资源路径。 禁止的资源名称包括 {"java/", "com/",
"com/ibm/", "META-INF/services/"}。 服务器会忽略这些输入以及在句法或语义上无效的任何输入。
当应用程序和其他工件提供相同的 OSS 软件包时,下列过程可能不运行。 如果应用程序和独立资源适配器 (配置为非隔离) 都提供了 OSS 软件包,那么可能两者都链接到资源适配器提供的软件包,并且在 ExtClassLoader 类路径上可视。 在此类部署中,您必须将独立资源适配器重新配置为隔离式,或者将先前提到的建议应用于应用程序部署 (例如,将应用程序类装入器授权方式设置为 Parent_last 或将隔离式共享库与应用程序相关联)。 缺省情况下,已启用始终受保护的软件包,且无法禁用。 您往往可以添加到始终受保护的软件包列表。
- 确定有问题的 OSS 框架的根软件包名称。 例如,Apache HTTP 组件的根软件包名称是 org.apache.http.。 Apache HTTP 组件中的所有类都将此根软件包名称用作前缀。 请参阅 开放式源代码软件 API 主题以获取更多信息。
- 在管理控制台的 "服务器设置" 页面上的 "服务器基础结构" 下,单击 。
- 选择 Java 虚拟机。
- 定义 JVM 通用自变量部分中的下列系统属性,如下所示:
- 定义系统属性 -Dws.ext.debug=true。
- 在 JVM 通用参数中定义系统属性 -Dcom.ibm.ws.classloader.server.alwaysProtectedPackages=<pkg1>,...,<pkgN> ,以从已部署的 Java EE 工件中隐藏 OSS 包 <pkg1>...<pkgN> 。 此设置自己应该隐藏有问题的 OSS 软件包。
- 始终受保护的软件包:com.ibm.ws.classloader.server.alwaysProtectedPackages
以逗号 (
',') 分隔的包名字符串, WebSphere Application Server 将这些包名与所有已部署的工件隔离 (保护)。 Always-受保护的软件包名称必须以'.'结尾,并且不能是任何禁止的软件包名称的子软件包。 WebSphere Application Server 将忽略无效的始终受保护的软件包名称。设置此属性时,只要
clsName包含始终受保护的包名作为前缀,ExtClassLoader资源 APIgetResource(rscName)就不会委派给 OSGi 网关。 仅当clsName在ExtClassLoader的本地类路径上可视时,此方法才会返回类。 同样,只要资源名称以 .class 结尾并且位于路径中,ExtClassLoader资源 API 就不会委派给 OSGi 网关。 转换为软件包名称之后,它包含始终受保护的软件包名称作为前缀。例如,如果包名 org.oss.pkg. 始终受保护,那么
ExtClassLoader.loadClass(org.oss.pkg.Unexpected)不会委派给 OSGi 网关,并且会有效地阻止任何 JEE 应用程序,共享库,定制认证模块,独立资源或定制服务意外链接到包 org.oss.pkg.中的类。同样,方法
ExtClassLoader.getResource(org/oss/pkg/Unexpected.class)不会委派给 OSGi 网关,这将进一步确保已部署的工件无法发现 WebSphere Application Server提供的 org.oss.pkg. 包中的类文件。缺省值为 unset。
- 如果已部署工件意外装入 WebSphere Application Server随附的 OSS 包所提供的资源,请定义系统属性 -Dcom.ibm.ws.classloader.server.alwaysProtectedResources=<rsc>,...,<rscN> 以隐藏已部署工件中的 OSS 资源路径 <rsc>...<rscN> 。
- 始终受保护的资源:com.ibm.ws.classloader.server.alwaysProtectedResources
一个
','分隔的资源名称字符串, WebSphere Application Server 将其与所有已部署的工件隔离 (保护)。 Always-受保护的资源名称不能以'/'开头 (必须是相对名称) ,不能以'/'结尾,并且不能是任何禁止的资源名称的子串。 WebSphere Application Server 将忽略无效的始终受保护的资源名称。设置此属性时,只要
rscName包含始终受保护的资源名称作为前缀,ExtClassLoader资源 API (getResource(rscName)) 就不会委派给 OSGi 网关。例如,如果资源名称 org/oss/pkg/ 始终受保护,那么
ExtClassLoader.getResource(org/oss/pkgs/unexpected)不会将操作委派给 OSGi 网关,并且会有效地阻止任何已部署的工件在 WebSphere Application Server提供的 org/oss/pkg/ 路径中发现资源。不必为始终受保护软件包中的 .class 文件指定始终受保护的资源名称,因为它们已受保护。
缺省值为 unset。
- 如果已部署的工件依赖于始终受保护的包中的子包或类,请在 JVM 通用参数中定义系统属性 -Dcom.ibm.ws.classloader.server.alwaysAllowedPackages=<pkgOrClass1>,...
,<pkgOrClassN> ,以使 OSS 包 <pkgOrClass1>...<pkgOrClassN> 可供已部署的 Java EE 工件访问。 当已部署的工件只需要始终受保护的 OSS 软件包内的某个接口时,最可能使用此设置。
- 始终允许的软件包:com.ibm.ws.classloader.server.alwaysAllowedPackages
WebSphere Application Server 使其对所有已部署工件可见的 "始终受保护" 包的子包或标准类名的
','分隔字符串。 WebSphere Application Server 将忽略无效的始终受保护的资源名称,包括绝对名称 (以'/'开头的名称)。 WebSphere Application Server 将忽略无效的始终允许的软件包名称。例如,如果包名 org.oss.pkg. 始终受保护,并且始终允许 org.oss.pkg.api. ,那么
ExtClassLoader. loadClass (org.oss.pkg.api.PkgFactory)会委派给 OSGi 网关,并允许已部署的类与 WebSphere Application Server提供的org.oss.pkg.api.PkgFactory链接; 但会阻止它链接到包 org.oss.pkgor 或 org.oss.pkg.impl中的类 (也由 WebSphere Application Server提供)。缺省值为 unset。
- 如果已部署的工件必须在始终受保护的资源路径的子路径中装入资源,请在 JVM 通用参数中定义系统属性 -Dcom.ibm.ws.classloader.server.alwaysAllowedResources=<rsc1>...<rscN> ,以使 OSS 资源 <rsc1>...<rscN> 可供已部署的 Java EE 工件访问。
- 始终允许的资源:com.ibm.ws.classloader.server.alwaysAllowedResources
','分隔的子路径字符串或 WebSphere Application Server 使其对所有已部署工件可见的始终受保护的资源 (路径) 的确切路径名。 WebSphere Application Server 将忽略无效的始终允许的资源名称。例如,如果资源名称 org/oss/pkg/始终受保护,并且始终允许 "org/oss/pkg/api/ ,那么方法
ExtClassLoader.getResource(org/oss/pkg/api/PkgFactory.class)会将其委派给 OSGi 网关,并允许已部署的类发现 WebSphere Application Server提供的 "org/oss/pkg/api/PkgFactory.class"; 但会阻止其发现路径 org/oss/pkg 或 org/oss/pkg/impl/中的资源 (也由 WebSphere Application Server提供)。缺省值为 unset。
- 单击应用。
- 单击确定。
- 保存更改。 请确保在重新启动服务器之前已完成文件同步。
- 重新启动 WebSphere Application Server 以使更改生效。
- 检查 native_stdout.log 并查找先前定义的系统属性。例如,当您指定始终受保护的软件包 org.apache.http. 时,可能会出现与下面类似的语句:
ProtectionMetaData.clinit: system property: com.ibm.ws.classloader.server.alwaysProtectedPackages=org.apache.http. ... ... ProtectionMetaData.clinit: always-protected packages: org.slf4j. org.slf4j.spi. org.slf4j.impl. org.slf4j.helpers. org.apache.http.如果您看到包包含在始终受保护的包的列表中 (例如,在先前示例中的 org.apache.http. 中) ,请正确配置服务器以隐藏 WebSphere Application Server提供的 OSS 包。 有其他软件包始终受服务器保护,例如 org.slf4j。 您的应用程序也将从这些软件包中收到保护。 如果在列表中看不到始终受保护的软件包,那么 native_stdout.log 的相同工作区域中会出现消息,指示忽略软件包的原因。 修改属性值,并重新启动服务器。
- 先移除系统属性 -Dws.ext.debug=true,然后再将新的服务器配置放在生产中。