并发类加载引起的死锁

2 篇文章 0 订阅
近来系统启动经常出现卡死现象,要启动几次才能起来,由于是OSGi环境,系统启动时会加载大量的类,并且由不同classloader加载,因此怀疑是类加载死锁,通过jconsole看到进程间相互等待的现象,通过dump 得到很多进程block的信息,分析找到问题位置
xxxxx.base.dao.Activator.registerPOJO在注册po时发生了死锁。由于使用OSGi时hibernate并不支持osgi环境,因此po的加载注册是平台自己写的。
定位到出现问题的位置后,下面来分析原因,
registerPOJO方法如下,

[img]http://dl2.iteye.com/upload/attachment/0098/7852/14296cbf-fbb0-3f53-8022-b3751f44454d.jpg[/img]

可以看到此方法是synchronized的,应该不会出现死锁,继续看方法中的parseBundleClasses方法

[img]http://dl2.iteye.com/upload/attachment/0098/7854/1ad60d97-9283-3823-88c7-e842d99fc09b.jpg[/img]

注意到此方法中存在synchronized静态变量,因此同时存在了类锁和对象锁,如果有一个线程拿到类锁,另外一个线程拿到对象锁,变出现了死锁,上网搜索发现阿里也出现过这个情况
http://alipaymiddleware.com/%E6%9C%8D%E5%8A%A1%E5%AE%B9%E5%99%A8/osgi%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%AD%BB%E9%94%81%E5%88%86%E6%9E%90/
文章中给出的解决方法稍后再说,我怀疑还有其他情况导致死锁,我们的po分布的不同的bundle中,但po中使用了枚举类型,而枚举会分布在其他bundle中,因此在加载本bundle的po时需要同时加载其枚举类型,这时会需要其他bundle的加载器进行加载,因此此线程出现阻塞,而其他bundle也需要其他bundle的加载器加载其需要的枚举类型,这样极有可能出现循环等待。
下面说一下解决方法,根据上面文章中提到的,解决的办法就是去掉锁和加锁,
去掉锁就是采用并发加载的方式,不同的线程就不会需要在去获取classloader的对象锁,也就不会有这个死锁的问题,同时并发加载的方式对于系统的性能是有提升的。加锁就是在加载自定义的类的时候也对当前的classloader对象进行加锁,这样可以保证不再出现死锁。
结合我们的实际代码,我觉得适合我们的
去掉锁
如果是jdk1.6可以升级到1.7或者在jvm中加入参数

dump信息

"SpringOsgiExtenderThread-74" prio=5 tid=104 BLOCKED
at java.lang.ClassLoader.checkCerts(ClassLoader.java:782)
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:487)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:625)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2279)
Local Variable: byte[]#2006
Local Variable: java.lang.String#71363
Local Variable: java.lang.String#71364
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1501)
Local Variable: java.util.HashSet#5911
Local Variable: java.lang.String#71365
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.apache.felix.framework.Felix.loadBundleClass(Felix.java:1844)
at org.apache.felix.framework.BundleImpl.loadClass(BundleImpl.java:937)
at gboat2.base.dao.Activator.parseBundleClasses(Activator.java:314)
Local Variable: org.apache.felix.framework.BundleImpl#35
Local Variable: java.lang.String#70146
Local Variable: java.lang.String#43279
Local Variable: java.util.AbstractList$Itr#23
Local Variable: java.lang.ClassNotFoundException#1
Local Variable: java.util.ArrayList#12164
Local Variable: java.util.AbstractList$Itr#22
Local Variable: java.util.ArrayList#12163
Local Variable: java.lang.String[]#2192
at gboat2.base.dao.Activator.registerPOJO(Activator.java:177)
at gboat2.base.dao.Activator.setApplicationContext(Activator.java:93)
Local Variable: java.util.LinkedHashMap#15659
Local Variable: java.util.LinkedHashMap#15601
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:117)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:396)
Local Variable: org.springframework.context.support.ApplicationContextAwareProcessor#2
Local Variable: java.util.AbstractList$Itr#24
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1475)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
Local Variable: class gboat2.base.dao.Activator
Local Variable: org.springframework.beans.BeanWrapperImpl#3
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
Local Variable: org.springframework.beans.factory.support.AbstractBeanFactory$1#3
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
Local Variable: java.util.ArrayList#11365
Local Variable: java.util.AbstractList$Itr#14
Local Variable: org.springframework.beans.factory.support.RootBeanDefinition#642
Local Variable: java.lang.String#55756
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
Local Variable: java.lang.String[]#1978
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)
Local Variable: org.springframework.beans.factory.support.DefaultListableBeanFactory#2
at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
Local Variable: org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4#12
Local Variable: org.springframework.osgi.util.BundleDelegatingClassLoader#8
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
Local Variable: org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext#7
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
Local Variable: java.lang.Object#341
Local Variable: org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask#12
at java.lang.Thread.run(Thread.java:662)

参考文档:
http://osdir.com/ml/dev-felix-apache/2009-04/msg00139.html
https://www.mail-archive.com/users@felix.apache.org/msg15209.html
https://bugs.eclipse.org/bugs/show_bug.cgi?id=121737
http://alipaymiddleware.com/%E6%9C%8D%E5%8A%A1%E5%AE%B9%E5%99%A8/osgi%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%AD%BB%E9%94%81%E5%88%86%E6%9E%90/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值