jdon导致cpu 99%最后tomcat死掉---banq给予回复

12-06-01 mianwo602
         

问题:最近发现客户的机器tomcat进程的cpu经常在99%基本上导致应用死掉

分析:通过分析,发现很多线程停留,查看堆栈信息如下:

http-80-1 RUNNABLE java.lang.Thread

java.util.HashMap.get(Unknown Source)

com.jdon.container.pico.JdonPicoContainer.getInstance(JdonPicoContainer.java:327)

com.jdon.container.pico.JdonPicoContainer.getComponentInstance(JdonPicoContainer.java:309)

org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)

org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:117)

org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getConstructorArguments(ConstructorInjectionComponentAdapter.java:193)

org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:148)

org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:56)

org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:184)

com.jdon.container.pico.PicoContainerWrapper.getComponentNewInstance(PicoContainerWrapper.java:197)

com.jdon.bussinessproxy.target.POJOObjectFactory.create(POJOObjectFactory.java:45)

com.jdon.bussinessproxy.target.DefaultTargetServiceFactory.create(DefaultTargetServiceFactory.java:59)

com.jdon.aop.reflection.MethodInvokerUtil.createTargetObject(MethodInvokerUtil.java:102)

com.jdon.aop.reflection.ProxyMethodInvocation.methodInvoke(ProxyMethodInvocation.java:97)

com.jdon.aop.reflection.ProxyMethodInvocation.proceed(ProxyMethodInvocation.java:76)

com.jdon.aop.interceptor.SessionContextInterceptor.invoke(SessionContextInterceptor.java:76)

com.jdon.aop.reflection.ProxyMethodInvocation.proceed(ProxyMethodInvocation.java:84)

com.jdon.aop.interceptor.StatefulInterceptor.invoke(StatefulInterceptor.java:82)

com.jdon.aop.reflection.ProxyMethodInvocation.proceed(ProxyMethodInvocation.java:84)

com.jdon.aop.interceptor.PoolInterceptor.invoke(PoolInterceptor.java:91)

com.jdon.aop.reflection.ProxyMethodInvocation.proceed(ProxyMethodInvocation.java:84)

com.jdon.aop.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:69)

com.jdon.aop.reflection.ProxyMethodInvocation.proceed(ProxyMethodInvocation.java:84)

com.jdon.aop.AopClient.invoke(AopClient.java:95)

com.jdon.bussinessproxy.dyncproxy.DynamicProxyWeaving.invoke(DynamicProxyWeaving.java:62)

$Proxy11.getKh_khddById(Unknown Source)

cn.vetech.framework.pszx.model.Kh_khdd_jcqp_tosave_action.checkB2BFKF(Kh_khdd_jcqp_tosave_action.java:943)

sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

java.lang.reflect.Method.invoke(Unknown Source)

org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:274)

org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:194)

org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419)

org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)

org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)

org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)

javax.servlet.http.HttpServlet.service(HttpServlet.java:617)

javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)

org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

cn.vetech.framework.asms.AgentFilter.doFilter(AgentFilter.java:54)

org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

com.jdon.util.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:92)

org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)

org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:615)

org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)

org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:877)

org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:594)

org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1675)

java.lang.Thread.run(Unknown Source)

这个线程基本上卡住,然后越来越多,线程是卡住在java.util.HashMap.get(Unknown Source)

,然后我查看com.jdon.container.pico.JdonPicoContainer.getInstance(JdonPicoContainer.java:327)

这个源码发现里面有一个专门缓存pojo这个配置的实例对象的一个hashmap,代码如下:

public Object getInstance(ComponentAdapter componentAdapter)

{

Object componentKey = componentAdapter.getComponentKey();

Object instance = this.componentKeyToInstanceCache.get(componentKey);

if ((instance == null) &&

(componentAdapter != null)) {

instance = getTrueInstance(componentAdapter);

if (instance != null) {

this.componentKeyToInstanceCache.put(componentKey, instance);

}

}

return instance;

}

这个代码其中 Object instance = this.componentKeyToInstanceCache.get(componentKey);的定义是:

public class JdonPicoContainer

implements MutablePicoContainer, Serializable

{

public static final String module = JdonPicoContainer.class.getName();

private Map componentKeyToAdapterCache = new HashMap();

private Map componentKeyToInstanceCache = new HashMap();

..............

componentKeyToInstanceCache 这个里面存放我定义的service和dao,jdon框架在我获取一个service或者dao的时候判断在这个componentKeyToInstanceCache里面有没有实例,如果没有就实例化一个对象并缓存到这个map中,下次我再次使用这个对象的时候直接从缓存里面取,那么问题是这个componentKeyToInstanceCache不是一个线程同步的对象,因为JdonPicoContainer是一个单例。componentKeyToInstanceCache这个对象相当于是一个全局的。因此如果多线程并发的应用下,这个地方肯定会出现问题。而我为了找这个问题已经都快疯了。然后我下载最新的jdon的框架发现,这个类已经被修改成 private Map componentKeyToInstanceCache = new ConcurrentHashMap(),既然做了调整为什么在网站上没有说明并告知。导致我们使用者带来巨大的麻烦。

本人可能分析有误见谅,希望作者给与回复

[该贴被mianwo602于2012-06-01 13:47修改过]

         

6
banq
2012-06-01 15:37

2012-06-01 13:41 "@mianwo602"的内容
既然做了调整为什么在网站上没有说明并告知。导致我们使用者带来巨大的麻烦。 ...

非常抱歉,给你带来这么多麻烦。

这部分代码原来是PicoContainer 1.1版本的,我进行了重写,后来发现它还存在并发问题,又一次进行了重写,抱歉没有及时通知。

现在最新版本经过多次并发测试,已经基本不存在死锁问题,唯一要注意的是JVM 永生代占有量大小变化,JVM上进行优化。

[该贴被banq于2012-06-01 15:39修改过]

mianwo602
2012-06-01 16:33

我现在没有更换高版本,只是把我那个版本的源码改了

改的内容是将hashmap换成了ConcurrentHashMap

banq老师您觉得这个还有问题吗?

banq
2012-06-01 16:47

关键要确认死锁在这里,用jstack将堆栈输出,寻找BLOCKING

mianwo602
2012-06-01 16:48

我现在没有更换高版本,只是把我那个版本的源码改了

改的内容是将hashmap换成了ConcurrentHashMap

banq老师您觉得这个还有问题吗?

我发现死锁的地方有3个大概是:

JdonPicoContainer

HttpSessionProxyVisitor

SessionContext

3Go 1 2 3 下一页