Tomcat运行含FrameworkUtil.getBundle的OSGI代码遇空值问题求助
核心原因
从Liberty迁移到Tomcat后,FrameworkUtil.getBundle(IdentityAssertionLoginModule.class)返回null的本质是类加载器隔离问题:Tomcat的应用类加载器与OSGI框架的类加载器相互独立,当IdentityAssertionLoginModule由Tomcat类加载器加载时,OSGI框架无法识别该类所属的bundle,导致无法获取对应的BundleContext。
具体修复方案
确保类由OSGI类加载器加载
检查IdentityAssertionLoginModule所在JAR的MANIFEST.MF,确认包含OSGI bundle必需的头信息(如Bundle-SymbolicName、Bundle-Version),确保该JAR被识别为OSGI bundle并由OSGI框架的类加载器加载,而非作为普通依赖放在Tomcat的WEB-INF/lib目录下。通过Activator静态持有BundleContext
放弃依赖FrameworkUtil,改为在bundle启动时将BundleContext存入静态变量,后续直接调用获取:public class MyBundleActivator implements BundleActivator { private static BundleContext bundleContext; @Override public void start(BundleContext context) throws Exception { MyBundleActivator.bundleContext = context; } @Override public void stop(BundleContext context) throws Exception { MyBundleActivator.bundleContext = null; } public static BundleContext getBundleContext() { return bundleContext; } }在需要使用BundleContext的代码中,直接调用
MyBundleActivator.getBundleContext()即可。调整Tomcat中OSGI容器的部署配置
若使用Apache Felix、Eclipse Equinox等嵌入Tomcat的OSGI容器,需将目标bundle部署到OSGI容器指定的bundle目录,而非Tomcat web应用的WEB-INF/lib,确保bundle被OSGI框架正确初始化和管理。类加载器验证(调试用)
临时添加代码打印类加载器信息,确认类的加载来源:System.out.println("类加载器:" + IdentityAssertionLoginModule.class.getClassLoader());若输出为Tomcat的
WebappClassLoader,说明类未被OSGI加载,需调整部署方式。
内容的提问来源于stack exchange,提问作者dtbdtbdtb

