`
roc08
  • 浏览: 227978 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

并发类加载引起的死锁

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



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



注意到此方法中存在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/
  • 大小: 75.5 KB
  • 大小: 58.4 KB
分享到:
评论

相关推荐

    进程调度与死锁-作业

    要判断系统是否安全,我们可以使用银行家算法来检查是否存在一个安全序列,即一系列进程可以在不引起死锁的情况下完成它们的任务。如果存在这样的序列,系统就是安全的;如果没有,系统可能陷入死锁状态。在这个具体...

    JVM---jstack分析Java线程CPU占用,线程死锁的解决

    Java虚拟机(JVM)是Java程序运行的基础,它负责管理程序的内存、线程以及类加载等核心功能。在开发和运维过程中,有时会遇到Java应用的性能问题,如线程CPU占用过高或者线程死锁。这时,我们就需要用到JVM提供的...

    JVM配置资料JVM配置资料

    - **PermGen/Metaspace Overflow**:持久代/元空间溢出,通常由于过多的类或大型静态变量引起,可通过增大相应区域大小或限制类加载。 9. **JIT编译器(Just-In-Time Compiler)**: - **HotSpot** JVM包含C1和C2...

    实战JAVA虚拟机 JVM故障诊断与性能优化.rar

    1. 类加载优化:避免过多的类加载,合理设计包结构,利用类加载器的双亲委托模型。 2. 内存调优:合理配置堆内存大小,根据应用特点调整新生代和老年代的比例,以提高垃圾回收效率。 3. 线程优化:减少不必要的线程...

    项目开发中碰到的一个线程问题 (二)

    1. **类加载器与类的单例模式**:反射可能破坏单例模式,因为不同的类加载器可以加载同一份类的多个实例,这在多线程环境下可能导致数据不一致。要避免这种情况,可以使用双检锁(Double-Check Locking)或其他线程...

    JVM调优和故障排除手册

    8. 类加载和解析问题:ClassNotFoundException(找不到类异常)和NoClassDefFoundError(未找到类定义错误)通常是由于类路径问题或类定义失败引起的。文档中提出了问题模式以及如何解决这些类加载相关的问题。 ...

    java面试总结

    在高并发处理方面,面试者需要掌握Java中线程的创建与管理、线程同步机制、锁机制、以及常用的并发工具类(如CountDownLatch、CyclicBarrier、Semaphore等)。了解线程安全的概念对于通过面试至关重要,尤其是对于...

    计算机操作系统期末考试题及答案1.pdf

    15. **死锁资源**:在并发系统中,CPU资源不会引起死锁,因为可以抢占,选项C正确。打印机、磁带机等I/O设备通常是非抢占的,可能导致死锁。 16. **作业调度算法**:最高响应比优先算法既照顾到了短作业,也考虑了...

    Java笔试题大汇总

    Java没有内置的死锁检测机制,需要程序员避免死锁的发生。 9. Java Applet安全限制:Applet在浏览器中运行,有安全限制,例如不能加载本地库(A),不能读取本地文件系统(B),也不能写入本地文件系统(C)。D...

    JAVA面试八股文JAVA面试八股文

    - **JVM**:理解内存模型(堆、栈、方法区等),垃圾收集机制,类加载过程等。 - **设计模式**:熟悉常见的设计模式,如工厂模式、单例模式、代理模式等,并能结合实际场景应用。 - **反射机制**:了解反射的用途...

    JVM下篇:性能监控与调优篇.7z

    - **类加载情况**:过多的类加载可能占用大量内存。 6. **调优策略**: - **根据应用特点选择合适的垃圾收集器**:例如,对响应时间要求高的应用可以选择G1 GC。 - **合理设置内存大小**:避免因内存过大导致的...

    操作系统期末复习.doc

    本篇文章将深入探讨操作系统中的关键知识点,包括并发性、共享性、虚拟存储、进程管理、调度算法、死锁、内存管理和I/O管理。 1. **并发性和共享性**是现代操作系统两个最基本的特征。并发性指的是多个任务或进程在...

    计算机操作系统期末考试题及答案(三)借鉴.pdf

    15. 在多进程系统中,CPU资源不会引起死锁,因为可以剥夺资源,选项C正确。 16. 最高响应比优先调度算法既考虑了等待时间,又考虑了服务时间,能兼顾短小作业和长作业,选项C正确。 17. 进程间的同步是指进程间的...

    操作系统测试题教学.pdf

    答案C错误,因为硬件故障中断并非总是由机器错误引起,也可能是因为正常工作状态下的报警。 3. 调度程序优化时间:通过合理调度,可以减少等待时间和空闲时间,提高系统效率。题目中的情况是通过调度减少了120ms的...

    最新操作系统试题及答案讲学.pdf

    33. **磁盘管理**:磁盘是独占型设备,分配不当可能导致死锁,但磁盘本身不会引起死锁。 34. **SPOOLING技术**:SPOOLING技术提高了独占设备的利用率,例如打印机的并行处理。 35. **创建进程**:在LINUX系统中,`...

    进程管理习题(不含答案)

    21. **死锁原因**:死锁可以由资源分配不当或进程间的循环等待引起。 22. **死锁影响**:一旦出现死锁,部分或所有相关进程无法继续执行。 23. **所有进程挂起与死锁**:所有进程挂起不一定会导致死锁,除非它们都...

    惠普 HP笔试题/口试题

    8. JDBC 连接数据库:通过 Class.forName() 加载驱动,DriverManager.getConnection() 创建连接。Statement 用于执行静态SQL,PreparedStatement 提供预编译的SQL,防止SQL注入,更高效。 9. 进程状态转换:进程从...

    操作系统全英文期末考试题(带答案).doc

    10. 内存管理中的页面替换:使用页面替换算法是为了处理主存不足的情况,将不再使用的页面替换到外存中,以便腾出空间加载新的页面。 这些知识点涵盖了操作系统的基本概念,如进程管理、内存管理、死锁预防、作业...

    操作系统全英文期末考试题(带答案).pdf

    3. 进程从等待状态转变为就绪状态通常是由进程调度引起的(题3),即系统选择了一个等待资源的进程并将其放入就绪队列,等待CPU执行。 4. 并发进程是指多个进程可以在同一时间段内执行,而不是绝对意义上的平行运行...

Global site tag (gtag.js) - Google Analytics