问题:最近发现客户的机器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修改过]