OSGI Bundle和Web容器加载类冲突问题的分析和解决
http://blog.csdn.net/achilles12345/article/details/7260000
上面这篇文章解释的算是比较清楚的。我自己遭遇的问题如下(HSF使用了log4j,我自己也使用了log4j,然后问题就来了):
- 信息: Dual registration of jndi stream handler: factory already defined
- log4j:WARN No appenders could be found for logger (com.taobao.remoting.common).
- log4j:WARN Please initialize the log4j system properly.
- DeployServer started, listen at: 12201
- log4j:ERROR Could not create an Appender. Reported error follows.
- java.lang.ClassCastException: org.apache.log4j.DailyRollingFileAppender cannot b
- e cast to org.apache.log4j.Appender
- at org.apache.log4j.xml.DOMConfigurator.parseAppender(DOMConfigurator.ja
- va:175)
- at org.apache.log4j.xml.DOMConfigurator.findAppenderByName(DOMConfigurat
- or.java:150)
- at org.apache.log4j.xml.DOMConfigurator.findAppenderByReference(DOMConfi
- gurator.java:163)
- at org.apache.log4j.xml.DOMConfigurator.parseChildrenOfLoggerElement(DOM
- Configurator.java:425)
- at org.apache.log4j.xml.DOMConfigurator.parseCategory(DOMConfigurator.ja
- va:345)
- at org.apache.log4j.xml.DOMConfigurator.parse(DOMConfigurator.java:827)
- at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java
- :712)
- at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java
- :618)
- at org.apache.log4j.xml.DOMConfigurator.configure(DOMConfigurator.java:7
- 43)
- at com.taobao.config.client.ConfigClientLogger.initialize(ConfigClientMa
- nager.java:52)
- at com.taobao.config.client.ConfigClientLogger.<clinit>(ConfigClientMana
- ger.java:102)
- at com.taobao.config.client.SubscriberRegistrar.<clinit>(SubscriberRegis
- trar.java:72)
- at com.taobao.hsf.model.metadata.component.MetadataComponent.subscriber(
- MetadataComponent.java:106)
- at com.taobao.hsf.process.component.ProcessComponent.consume(ProcessComp
- onent.java:107)
- at com.taobao.hsf.app.spring.util.HSFSpringConsumerBean.init(HSFSpringCo
- nsumerBean.java:251)
- at com.taobao.hsf.app.spring.util.HSFSpringConsumerBean.afterPropertiesS
- et(HSFSpringConsumerBean.java:264)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.createBean(AbstractAutowireCapableBeanFactory.java:456)
- at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb
- ject(AbstractBeanFactory.java:294)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
- y.getSingleton(DefaultSingletonBeanRegistry.java:225)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetB
- e
- an(AbstractBeanFactory.java:291)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
- (AbstractBeanFactory.java:193)
- at org.springframework.beans.factory.support.DefaultListableBeanFactory.
- preInstantiateSingletons(DefaultListableBeanFactory.java:591)
- at org.springframework.context.support.AbstractApplicationContext.finish
- BeanFactoryInitialization(AbstractApplicationContext.java:918)
- at org.springframework.context.support.AbstractApplicationContext.refres
- h(AbstractApplicationContext.java:469)
- at org.springframework.web.context.ContextLoader.configureAndRefreshWebA
- pplicationContext(ContextLoader.java:383)
- at org.springframework.web.context.ContextLoader.initWebApplicationConte
- xt(ContextLoader.java:283)
- at org.springframework.web.context.ContextLoaderListener.contextInitiali
- zed(ContextLoaderListener.java:111)
- at org.apache.catalina.core.StandardContext.listenerStart(StandardContex
- t.java:3934)
- at org.apache.catalina.core.StandardContext.start(StandardContext.java:4
- 429)
- at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
- at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
- at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
- at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443
- )
- at org.apache.catalina.core.StandardService.start(StandardService.java:5
- 16)
- at org.apache.catalina.core.StandardServer.start(StandardServer.java:710
- )
- at org.apache.catalina.startup.Catalina.start(Catalina.java:583)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
- java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
- sorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
- at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
- log4j:ERROR Could not parse url [bundleresource://2/configclient.log4j.xml].
- java.lang.NullPointerException
- at java.util.Hashtable.put(Hashtable.java:394)
- at org.apache.log4j.xml.DOMConfigurator.findAppenderByName(DOMConfigurat
- or.java:151)
- at org.apache.log4j.xml.DOMConfigurator.findAppenderByReference(DOMConfi
- gurator.java:163)
- at org.apache.log4j.xml.DOMConfigurator.parseChildrenOfLoggerElement(DOM
- Configurator.java:425)
- at org.apache.log4j.xml.DOMConfigurator.parseCategory(DOMConfigurator.ja
- va:345)
- at org.apache.log4j.xml.DOMConfigurator.parse(DOMConfigurator.java:827)
- at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java
- :712)
- at org.apache.log4j.xml.DOMConfigurator
- .doConfigure(DOMConfigurator.java
- :618)
- at org.apache.log4j.xml.DOMConfigurator.configure(DOMConfigurator.java:7
- 43)
- at com.taobao.config.client.ConfigClientLogger.initialize(ConfigClientMa
- nager.java:52)
- at com.taobao.config.client.ConfigClientLogger.<clinit>(ConfigClientMana
- ger.java:102)
- at com.taobao.config.client.SubscriberRegistrar.<clinit>(SubscriberRegis
- trar.java:72)
- at com.taobao.hsf.model.metadata.component.MetadataComponent.subscriber(
- MetadataComponent.java:106)
- at com.taobao.hsf.process.component.ProcessComponent.consume(ProcessComp
- onent.java:107)
- at com.taobao.hsf.app.spring.util.HSFSpringConsumerBean.init(HSFSpringCo
- nsumerBean.java:251)
- at com.taobao.hsf.app.spring.util.HSFSpringConsumerBean.afterPropertiesS
- et(HSFSpringConsumerBean.java:264)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBean
- Factory.createBean(AbstractAutowireCapableBeanFactory.java:456)
- at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb
- ject(AbstractBeanFactory.java:294)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
- y.getSingleton(DefaultSingletonBeanRegistry.java:225)
- at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBe
- an(AbstractBeanFactory.java:291)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
- (AbstractBeanFactory.java:193)
- at org.springframework.beans.factory.support.DefaultListableBeanFactory.
- preInstantiateSingletons(DefaultListableBeanFactory.java:591)
- at org.springframework.context.support.AbstractApplicationContext.finish
- BeanFactoryInitialization(AbstractApplicationContext.java:918)
- at org.springframework.context.support.AbstractApplicationContext.refres
- h(AbstractApplicationContext.java:469)
- at org.springframework.web.context.ContextLoader.configureAndRefreshWebA
- pplicationContext(ContextLoader.java:383)
- at org.springframework.web.context.ContextLoader.initWebApplicationConte
- xt(ContextLoader.java:283)
- at org.springframework.web.context.ContextLoaderListener.contextInitiali
- zed(ContextLoaderListener.java:111)
- at org.apache.catalina.core.StandardContext.listenerStart(StandardContex
- t.java:3934)
- at org.apache.catalina.core.StandardContext.start(StandardContext.java:4
- 429)
- at org.apache.catalina.core.C
- ontainerBase.start(ContainerBase.java:1045)
- at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
- at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
- at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443
- )
- at org.apache.catalina.core.StandardService.start(StandardService.java:5
- 16)
- at org.apache.catalina.core.StandardServer.start(StandardServer.java:710
- )
- at org.apache.catalina.startup.Catalina.start(Catalina.java:583)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
- java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
- sorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
- at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
- [2012-12-14 10:07:52,121] [main] WARN com.mchange.v2.c3p0.management.ActiveMana
- gementCoordinator - A C3P0Registry mbean is already registered. This probably m
- eans that an application using c3p0 was undeployed, but not all PooledDataSource
- s were closed prior to undeployment. This may lead to resource leaks over time.
- Please take care to close all PooledDataSources.
- 2012-12-14 10:07:53 org.apache.coyote.http11.Http11Protocol start
- 信息: Starting Coyote HTTP/1.1 on http-8080
- 2012-12-14 10:07:53 org.apache.jk.common.ChannelSocket init
- 信息: JK: ajp13 listening on /0.0.0.0:8009
- 2012-12-14 10:07:53 org.apache.jk.server.JkMain start
- 信息: Jk running ID=0 time=0/16 config=null
- 2012-12-14 10:07:53 org.apache.catalina.startup.Catalina start
- 信息: Server startup in 6509 ms
核心指示是这一句:
- java.lang.ClassCastException: org.apache.log4j.DailyRollingFileAppender cannot b
- e cast to org.apache.log4j.Appender
根源就是org.apache.log4j.DailyRollingFileAppender的一个实例无法转换成org.apache.log4j.Appender,
虽然,这两个类存在是子-父关系,但是,DailyRollingFileAppender的实例所对应的类与org.apache.log4j.Appender不是由同一个类加载器加载,这就导致无法转型。
注意,具体分析的话,需要调试,把类的加载器给弄出来,才能真正搞清楚。因为,因为当前类的上下文加载器是可以被更换的,所以,产生冲突的情形会更复杂,需要具体场景具体分析。
至于为什么会产生转型,多半是将对象放入了某个容器,然后不同的上下文将容器中的实例取出来,这个时候就会发生转型失败。因为类型是兼容的,所以,编译器无法把关。只有在运行时才会报错。
稍微提一下,淘宝的HSF在反序列化时,可以访问应用自身的类,那是因为HSF使用web context classloader来载入这样的实体类,反序列化后,返回给HSF消费者。这时可以确保和消费者是同一个类的加载器加载,所以,就不再会发生转型失败。