osgi加载模式引发的错误
来源:互联网 发布:ubuntu下安装win10 编辑:程序博客网 时间:2024/06/04 04:45
今天,一个osgi项目运行出现了ClassCastException异常,具体情况下面介绍一下:
1、项目
一个运行在servicemix上的OSGi项目,使用activemq进行异步通信,接收方运行在服务器上,主要代码如下:
/** * JMS消息监听器 */public class Test implements MessageListener { //监听的队列名 private final String queueName = "zhs/test"; //连接工厂,通过服务注入 private ConnectionFactory connectionFactory; private Session session; private Connection connection; //开始监听队列 public void start() { try { connection = connectionFactory.createConnection(); connection.start(); session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(session.createQueue(queueName)); //当监听到信息,调用onMessage方法 consumer.setMessageListener(this); } catch (Exception e) { //... } } @Override public void onMessage(Message message) { try { String data = null; //转换message类型 ActiveMQBytesMessage bytesMessage = (ActiveMQBytesMessage) message; data = new String(bytesMessage.getContent().getData()); LOGGER.info("收到信息:" + data); session.commit(); } catch (Exception e) { LOGGER.error("接收信息时发生异常", e); } } public void setConnectionFactory(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; } }
上面的代码功能很简单,直接简单的将受到的信息记录到日志上
这个bundle启动正常,但是在接受信息时出现ClassCastException异常:message明明是ActiveMQbytesMessage类型,但为什么无法转换?
首先应该想到的是类加载器的不同引起的问题,我们把这两个类的类加载器打印出来看一下:
在接受到信息时添加记录:
ClassLoader cl1 = message.getClass().getClassLoader(); LOGGER.warn("接受到的信息类加载器:"+cl1); ClassLoader cl2 = ActiveMQBytesMessage.class.getClassLoader(); LOGGER.warn("ActiveMQBytesMessage的类加载路径:"+cl2);
结果出来了:
cl1显示:org.apache.activemq.activemq-osgi [89]
cl2显示:com.test [282]
解释一下:onMessage ( Message message ) 这个方法中,参数message来自org.apache.activemq.activemq-osgi,id为89的bundle
而我们希望转换的ActiveMQbytesMessage类型来自com.test,即本项目
OSGi的核心在于其复杂的类加载机制,一不小心就会发生类加载的错误,下面找一下错误发生的地方:
首先看onMessage ( Message message )这个方法中message的来源:是从信息队列中得到的信息,而信息队列是由activemq连接工厂来监听的(参考上面的代码),那么我们就找连接工厂是怎样注入的
高度模块化的OSGi项目中,这些公共依赖一般都是通过注入来实现了,这里,activemq的连接工厂通过监听osgi服务来注入,看blueprint的配置:
<!-- 引用 activemq jms connection factory 服务 --> <reference id="connectionFactory" timeout="0" interface="javax.jms.ConnectionFactory" filter="(osgi.jndi.service.name=jms/activemq-connection-fctory/zhs-dev-amq)" /> <!-- 信息监听器 --> <bean class="com.Test" init-method="start" destroy-method="stop"> <property name="connectionFactory" ref="connectionFactory" /> </bean>
看到了吗?连接工厂是通过监听一个名称为“jms/activemq-connection-fctory/zhs-dev-amq”的服务来注入的,下面追踪这个服务发现是由org.apache.activemq.activemq-osgi [89]提供的,也就是上面的cd1
下面看希望转换的ActiveMQbytesMessage类型为何来自我们本身的项目:
这个项目有一个外部jar包懒得转换为bundle,就直接集成在bundle里面,pom中有一个地方:
<Embed-Dependency>*</Embed-Dependency><Embed-Directory>lib/</Embed-Directory><Embed-StripGroup>true</Embed-StripGroup>
这个是把lib包中的所有jar包含到bundle的ClassPath下面,这样ActiveMQbytesMessage就来自bundle本身的ClassPath了
解决办法:知道了原理,解决就很容易了,修改任意一方的加载路径即可
- osgi加载模式引发的错误
- 由延时加载的单例模式引发的思考
- OSGI的类加载机制
- / 引发的错误
- snprintf引发的错误
- =引发的错误
- arc 引发的错误
- TreeSet引发的OSGI服务代理创建异常
- Part4. OSGi的类加载架构
- 【JVM】OSGi 灵活的类加载结构
- SpringMVC+Hibernate 一个经典的由懒加载机制引发的错误
- 【OSGi】OSGi类加载流程
- 【OSGi】OSGi类加载流程
- OSGI组件启动异常的错误解决方法
- 变量溢出引发的错误
- 一个分号引发的错误
- 字符集引发的编译错误
- 字符集引发的编译错误
- Hdu 2040(水题) 解题报告
- iterm2配置sz rz 命令实现上传下载
- 阿里云linux web服务器 相关配置
- C/C++判断文件是否存在
- Android-Spelling Checker Framework
- osgi加载模式引发的错误
- window10下出现宽带断线解决办法
- 【LEETCODE】231-Power of Two
- Java Unicode 编码互转
- 问题贴,谁告诉我这作业如何完成
- <img>
- STL_算法_最小值和最大值(min_element、max_element)
- 设计模式系列模式总预览
- 摄像头处理yuv转RGB的计算方法: