cpu过高,并居高不下

1.查找应用的pid
2.查找pid对应下的线程的哪些id过高
3.jstack pid连续两次获取堆栈的信息,查看变化,以及对应的线程

Thread 5812: (state = BLOCKED)
 - java.lang.Object.wait(long) @bci=0 (Interpreted frame)
 - java.lang.Object.wait() @bci=2, line=485 (Interpreted frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.await() @bci=8, line=458 (Interpreted frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.run() @bci=11, line=484 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=662 (Interpreted frame)


Thread 31207: (state = IN_JAVA)
   java.lang.CharSequence) @bci=54, line=3744 (Compiled frame)
 - java.util.regex.Pattern$GroupHead.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=28, line=4168 (Compiled frame)
 - java.util.regex.Pattern$Loop.matchInit(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=39, line=4311 (Interpreted frame)
 - java.util.regex.Pattern$Prolog.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=7, line=4251 (Interpreted frame)
 - java.util.regex.Pattern$Begin.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=30, line=3120 (Interpreted frame)
 - java.util.regex.Matcher.match(int, int) @bci=86, line=1127 (Compiled frame)
 - java.util.regex.Matcher.matches() @bci=6, line=502 (Interpreted frame)
 - com.jd.edmfont.action.MailSubscriptionAction.checkAndGetMailAddress() @bci=155, line=236 (Interpreted frame)
 - com.jd.edmfont.action.MailSubscriptionAction.mailOrder() @bci=45, line=132 (Interpreted frame)
 - sun.reflect.GeneratedMethodAccessor229.invoke(java.lang.Object, java.lang.Object[]) @bci=36 (Interpreted frame)
 - sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=25 (Compiled frame)
 - java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=161, line=597 (Compiled frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(java.lang.Object, com.opensymphony.xwork2.config.entities.ActionConfig) @bci=228, line=450 (Interpreted frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly() @bci=14, line=289 (Compiled frame)
 com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(com.opensymphony.xwork2.ActionInvocation) @bci=6, line=265 (Interpreted frame)
 - org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(com.opensymphony.xwork2.ActionInvocation) @bci=202, line=68 (Interpreted frame)
 - com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(com.opensymphony.xwork2.ActionInvocation) @bci=10, line=98 (Interpreted frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invoke() @bci=82, line=246 (Compiled frame)
 org.apache.struts2.dispatcher.Dispatcher.serviceAction(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, org.apache.struts2.dispatcher.mapper.ActionMapping) @bci=212, line=546 (Interpreted frame)
 - org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.apache.struts2.dispatcher.mapper.ActionMapping) @bci=11, line=77 (Interpreted frame)
 - org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) @bci=149, line=91 (Interpreted frame)
 - org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=119, line=235 (Interpreted frame)
 - org.apache.catalina.core.ApplicationFilterChain.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=101, line=206 (Interpreted frame)
 - com.jd.common.web.filter.CharsetFilter.doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) @bci=166, line=59 (Interpreted frame)
 - org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=119, line=235 (Interpreted frame)
 org.apache.catalina.connector.CoyoteAdapter.service(org.apache.coyote.Request, org.apache.coyote.Response) @bci=158, line=291 (Interpreted frame)
 - org.apache.coyote.http11.Http11Processor.process(java.net.Socket) @bci=514, line=859 (Interpreted frame)
 - org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(java.net.Socket) @bci=82, line=602 (Interpreted frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.run() @bci=41, line=489 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=662 (Interpreted frame)


Thread 31203: (state = IN_JAVA)
 - java.lang.Character.codePointAt(java.lang.CharSequence, int) @bci=5, line=2335 (Compiled frame; information may be imprecise)
 - java.util.regex.Pattern$CharProperty.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=10, line=3344 (Compiled frame)
 - java.util.regex.Pattern$Loop.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=139, line=4304 (Compiled frame)
 - java.util.regex.Pattern$GroupTail.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=70, line=4227 (Compiled frame)
 - java.util.regex.Pattern$GroupHead.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=28, line=4168 (Compiled frame)
 - java.util.regex.Pattern$Loop.matchInit(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=39, line=4311 (Interpreted frame)
 - java.util.regex.Pattern$Prolog.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=7, line=4251 (Interpreted frame)
 - java.util.regex.Pattern$Begin.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=30, line=3120 (Interpreted frame)
 - java.util.regex.Matcher.match(int, int) @bci=86, line=1127 (Compiled frame)
 - java.util.regex.Matcher.matches() @bci=6, line=502 (Interpreted frame)
 - com.jd.edmfont.action.MailSubscriptionAction.checkAndGetMailAddress() @bci=155, line=236 (Interpreted frame)
 - com.jd.edmfont.action.MailSubscriptionAction.mailOrder() @bci=45, line=132 (Interpreted frame)
 - sun.reflect.GeneratedMethodAccessor229.invoke(java.lang.Object, java.lang.Object[]) @bci=36 (Interpreted frame)
 - sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) @bci=6, line=25 (Compiled frame)
 - java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) @bci=161, line=597 (Compiled frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(java.lang.Object, com.opensymphony.xwork2.config.entities.ActionConfig) @bci=228, line=450 (Interpreted frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly() @bci=14, line=289 (Compiled frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invoke() @bci=111, line=252 (Compiled frame)
com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(com.opensymphony.xwork2.ActionInvocation) @bci=525, line=191 (Interpreted frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invoke() @bci=82, line=246 (Compiled frame)
 - org.apache.struts2.interceptor.MultiselectInterceptor.intercept(com.opensymphony.xwork2.ActionInvocation) @bci=121, line=73 (Interpreted frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invoke() @bci=82, line=246 (Compiled frame)
 com.jd.edmfont.action.EdmBaseInterceptor.intercept(com.opensymphony.xwork2.ActionInvocation) @bci=66, line=47 (Interpreted frame)
 - com.opensymphony.xwork2.DefaultActionInvocation.invoke() @bci=82, line=246 (Compiled frame)
 - org.apache.struts2.impl.StrutsActionProxy.execute() @bci=20, line=54 (Interpreted frame)
 - org.apache.struts2.dispatcher.Dispatcher.serviceAction(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.ServletContext, org.apache.struts2.dispatcher.mapper.ActionMapping) @bci=212, line=546 (Interpreted frame)
 - org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.apache.struts2.dispatcher.mapper.ActionMapping) @bci=11, line=77 (Interpreted frame)
org.apache.catalina.connector.CoyoteAdapter.service(org.apache.coyote.Request, org.apache.coyote.Response) @bci=158, line=291 (Interpreted frame)
 - org.apache.coyote.http11.Http11Processor.process(java.net.Socket) @bci=514, line=859 (Interpreted frame)
 - org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(java.net.Socket) @bci=82, line=602 (Interpreted frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.run() @bci=41, line=489 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=662 (Interpreted frame)


Thread 31195: (state = BLOCKED)
 - java.lang.Object.wait(long) @bci=0 (Interpreted frame)
 - java.lang.Object.wait() @bci=2, line=485 (Interpreted frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.await() @bci=8, line=458 (Interpreted frame)
 - org.apache.tomcat.util.net.JIoEndpoint$Worker.run() @bci=11, line=484 (Interpreted frame)
 - java.lang.Thread.run() @bci=11, line=662 (Interpreted frame)

4.根据堆栈的信息,cpu过高在的线程id,定位到相应的调用
 
 - java.util.regex.Pattern$GroupHead.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=28, line=4168 (Compiled frame; information may be imprecise)
 - java.util.regex.Pattern$Loop.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=106, line=4295 (Compiled frame)
 - java.util.regex.Pattern$GroupTail.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=70, line=4227 (Compiled frame)
 - java.util.regex.Pattern$Ques.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=68, line=3691 (Compiled frame)
 - java.util.regex.Pattern$Ques.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=68, line=3691 (Compiled frame)
 - java.util.regex.Pattern$Curly.match0(java.util.regex.Matcher, int, int, java.lang.CharSequence) @bci=141, line=3782 (Compiled frame)
 - java.util.regex.Pattern$Curly.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=54, line=3744 (Compiled frame)
 - java.util.regex.Pattern$GroupHead.match(java.util.regex.Matcher, int, java.lang.CharSequence) @bci=28, line=4168 (Compiled frame)

5.根据定位到的信息可以猜测到应该是正则死循环
6.然后查看代码

 String checkemail = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        Pattern regexemail = Pattern.compile(checkemail);
        if (mailAddress != null) {
            if (!regexemail.matcher(mailAddress).matches()) {
                mailAddress = null;
            }
        }

7.没有循环调用,然后百度google java 正则 死循环 cpu过高
8.sun官网已经有提交的bug,然后得到线上java版本 比较是否是同样问题,根据描述看能否复现
9.发现字符串长度到30左右确实可以复现,接着换成以前检验邮箱的正则,用同样的代码看是否有问题,发现没有问题了,说明是正则的问题
10.仔细检查正则,可以用asm修改Pattern的字节码,增加打印信息,调试,发现假死

  
public class MethodCallCountTransformer implements ClassFileTransformer {
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        try {
            if (!"java/util/regex/Pattern$CharProperty".equals(className)
                    && !"java/util/regex/Pattern$BmpCharProperty".equals(className)) {
                return classfileBuffer;
            }

            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            ClassAdapter adapter = new MethodCallClassAdapter(writer, className,"match");

            ClassReader reader = new ClassReader(classfileBuffer);
            reader.accept(adapter, 0);

            // 生成新类字节码
            return writer.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();

            // 返回旧类字节码
            return classfileBuffer;
        }
    }
    public static void premain(String options, Instrumentation ins) {
           //注册我自己的字节码转换器
           ins.addTransformer(new MethodCallCountTransformer());
   }

}

 
  public MethodCallClassAdapter(ClassVisitor classVisitor,String className,String methodName) {
        super(classVisitor);
        this.className=className;
        this.methodName=methodName;
    }
    // 重写 visitMethod,访问到 "operation" 方法时,
        // 给出自定义 MethodVisitor,实际改写方法内容
        public MethodVisitor visitMethod(final int access, final String name,
            final String desc, final String signature, final String[] exceptions) {
            MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions);
            MethodVisitor wrappedMv = mv;
            if (mv != null) {
                // 对于 "operation" 方法
                if (name.equals(methodName)) {
                    // 使用自定义 MethodVisitor,实际改写方法内容
                    wrappedMv = new CountCallMethodAdapter(mv,className,methodName);
                }
//                else if (name.equals("<init>")) {
//                             wrappedMv = new ChangeToChildConstructorMethodAdapter(mv,
//                                     className);
//                             }
            }
            return wrappedMv;
        }

     
 @Override
    public void visitCode() {

        visitLdcInsn(className);
        visitLdcInsn(methodName);

     mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/jd/tuhao/agent/Counter", "printAndIncCount", "(Ljava/lang/String;Ljava/lang/String;)V");
        super.visitCode();
    }

  
public class Counter {
    private static AtomicInteger methodCallCount = new AtomicInteger(0);

    public static void printAndIncCount(String className, String methodName) {
        System.out.println(className + "." + methodName + " called, total times " + methodCallCount.incrementAndGet());
    }
   
}


   打印信息:
  
java/util/regex/Pattern$BmpCharProperty.match called, total times 424
java/util/regex/Pattern$CharProperty.match called, total times 425
java/util/regex/Pattern$CharProperty.match called, total times 426
java/util/regex/Pattern$CharProperty.match called, total times 427
java/util/regex/Pattern$CharProperty.match called, total times 428
java/util/regex/Pattern$CharProperty.match called, total times 429
java/util/regex/Pattern$CharProperty.match called, total times 430
java/util/regex/Pattern$CharProperty.match called, total times 431
java/util/regex/Pattern$CharProperty.match called, total times 432
java/util/regex/Pattern$CharProperty.match called, total times 433
java/util/regex/Pattern$CharProperty.match called, total times 434
java/util/regex/Pattern$BmpCharProperty.match called, total times 435
java/util/regex/Pattern$CharProperty.match called, total times 436
java/util/regex/Pattern$BmpCharProperty.match called, total times 437
java/util/regex/Pattern$CharProperty.match called, total times 438
java/util/regex/Pattern$BmpCharProperty.match called, total times 439
java/util/regex/Pattern$CharProperty.match called, total times 440

猜你喜欢

转载自tofhao.iteye.com/blog/1897540
今日推荐