Boz*_*zho 10 java spring spring-mvc
我在我的日志文件中多次看到此异常:
调用请求方法导致异常:public static native long java.lang.System.currentTimeMillis()
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)
Run Code Online (Sandbox Code Playgroud)
是的,我的代码都没有.异常意味着处理程序方法返回了一个long数字,但它只能返回一组有限的类型.
我没有意识到的是如何System.currentTimeMillis()实现作为处理程序方法?
**更新:这已在Spring 3.1.2中修复**
我相信这确实是由竞争条件引起的.我已经为它创建了一个Jira问题,我试图解释会发生什么:https://jira.springsource.org/browse/SPR-9138
以下是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;
}
Run Code Online (Sandbox Code Playgroud)
它们System.currentTimeMillis()在异常处理程序方法的缓存中用作虚拟值:
// dummy method placeholder
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", null);
Run Code Online (Sandbox Code Playgroud)
并且它在没有检查的情况下泄漏(如果由(1)和(2)之间的另一个线程插入).甚至可能是无争,由于之间的差异thrownExceptionType和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;
}
}
Run Code Online (Sandbox Code Playgroud)
见AnnotationMethodHandlerExceptionResolver.java.
| 归档时间: |
|
| 查看次数: |
7779 次 |
| 最近记录: |