2011-04-13 9 views
10

acabo de ver esta excepción de un número de veces en mis archivos de registro:Spring MVC excepción - método de invocación de petición provocó una excepción: públicos java.lang.System.currentTimeMillis largos nativos estáticos()

Invocación de método de petición provocó una excepción: java.lang.System.currentTimeMillis públicas estáticas nativos largos()

java.lang.IllegalArgumentException: Invalid handler method return value: 1302697287376 
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver.getModelAndView(AnnotationMethodHandlerExceptionResolver.java:410) 
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver.doResolveException(AnnotationMethodHandlerExceptionResolver.java:140) 
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:136) 
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:987) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:811) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.mortbay.servlet.UserAgentFilter.doFilter(UserAgentFilter.java:78) 
    at org.mortbay.servlet.GzipFilter.doFilter(GzipFilter.java:154) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:636) 

Sí, ninguno de mi código está ahí. Lo que la excepción significa es que un método de controlador ha devuelto un número long, pero solo puede devolver un conjunto limitado de tipos.

Lo que no me doy cuenta es ¿cómo se realizó el método System.currentTimeMillis() como controlador?

+0

Ni idea, pero buscando en Google la excepción cedí este tema que contiene posiblemente información interesante http://forum.springsource.org/archive/index.php/t-66592.html – BalusC

+0

Sí, también lo he visto, pero carece de la definición del método, y eso es lo extraño aquí . – Bozho

+0

¿Está el "Método de solicitud de invocación ..." también del archivo de registro? – Ralph

Respuesta

5

Ellos utilizan System.currentTimeMillis() como un valor ficticio en una caché de métodos de controlador de excepciones:

// dummy method placeholder 
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", null); 

Y fugas sin verificación bajo contención (si está insertada por otro subproceso entre (1) y (2)). O tal vez incluso sin la contención debido a la diferencia entre thrownExceptionType y closestMatch:

private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) { 
    ... 
    Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache.get(handlerType); 

    if (handlers != null) { 
     handlerMethod = handlers.get(thrownExceptionType); // 1 
     if (handlerMethod != null) { 
      return (handlerMethod == NO_METHOD_FOUND ? null : handlerMethod); 
     } 
    } 
    ... 
    final Map<Class<? extends Throwable>, Method> resolverMethods = handlers; 
    ... 
    handlerMethod = getBestMatchingMethod(resolverMethods, thrownException); // 2 
    handlers.put(thrownExceptionType, (handlerMethod == null ? NO_METHOD_FOUND : handlerMethod)); 
    return handlerMethod; 
} 

private Method getBestMatchingMethod(
     Map<Class<? extends Throwable>, Method> resolverMethods, Exception thrownException) { 

    if (!resolverMethods.isEmpty()) { 
     Class<? extends Throwable> closestMatch = 
       ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException); 
     return resolverMethods.get(closestMatch); 
    } 
    else { 
     return null; 
    } 
} 

Ver AnnotationMethodHandlerExceptionResolver.java.

+2

aha .. tal vez un problema es ser informado allí. Ese método ficticio es bastante inútil. Estaba empezando a pensar que alguien está tratando de abusar del sistema pasando parámetros y llamando a métodos estáticos arbitrarios :) Pero de todos modos, todavía no entiendo qué causa el uso de un ExceptionResolver. ¿Cuál sería la excepción original? – Bozho

7

** Actualización: Esto se ha corregido en la primavera 3.1.2 **

Creo que esto es, en efecto causado por una condición de carrera. He creado un problema de Jira para ello, donde he tratado de explicar lo que sucede: https://jira.springsource.org/browse/SPR-9138

He aquí un extracto de la explicación del tema jira:

private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) { 
    //T1 and T2 enters method 
    final Class<?> handlerType = ClassUtils.getUserClass(handler); 
    final Class<? extends Throwable> thrownExceptionType = thrownException.getClass(); 
    Method handlerMethod = null; 

    Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache.get(handlerType); 
    //Timing makes (handlers==null) for T1 (handler != null) for T2 
    if (handlers != null) { 
     handlerMethod = handlers.get(thrownExceptionType); 
     //handlerMethod is still null for T2 
     if (handlerMethod != null) { 
      return (handlerMethod == NO_METHOD_FOUND ? null : handlerMethod); 
     } 
    } 
    else { 
     //T1 does this, the hashmap created here is read by T2 in if-test above matching this else block 
     handlers = new ConcurrentHashMap<Class<? extends Throwable>, Method>(); 
     exceptionHandlerCache.put(handlerType, handlers); 
    } 

    //handlers is empty for both T1 and T2, the two threads' resolverMethod variables will reference the same 
    // ConcurrentHashMap instance 
    final Map<Class<? extends Throwable>, Method> resolverMethods = handlers; 

    //This block does not find a match for the exception 
    ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { 
     public void doWith(Method method) { 
      method = ClassUtils.getMostSpecificMethod(method, handlerType); 
      List<Class<? extends Throwable>> handledExceptions = getHandledExceptions(method); 
      for (Class<? extends Throwable> handledException : handledExceptions) { 
       if (handledException.isAssignableFrom(thrownExceptionType)) { 
        if (!resolverMethods.containsKey(handledException)) { 
         resolverMethods.put(handledException, method); 
        } else { 
         Method oldMappedMethod = resolverMethods.get(handledException); 
         if (!oldMappedMethod.equals(method)) { 
          throw new IllegalStateException(
            "Ambiguous exception handler mapped for " + handledException + "]: {" + 
              oldMappedMethod + ", " + method + "}."); 
         } 
        } 
       } 
      } 
     } 
    }); 
    //T1 finds no match and puts NO_METHOD_FOUND in cache and returns null 
    // When T2 hits this line resolverMethods for T2 reference the same Map that T1 just put the NO_METHOD_FOUND 
    // as a result getBestMatchingMethod will return NO_SUCH_METHOD_FOUND (System.timeMillis()) which will be invoked 
    // by the doResolveException further up the callstack. 
    handlerMethod = getBestMatchingMethod(resolverMethods, thrownException); 
    handlers.put(thrownExceptionType, (handlerMethod == null ? NO_METHOD_FOUND : handlerMethod)); 
    return handlerMethod; 
} 
Cuestiones relacionadas