[小坑一个]java.lang.ClassCastException: java.util.SubList cannot be cast to java.uti

最新公司的电商平台上了个内测版本, 测试用户报告了一个严重错误, 在某些情况下可能导致产品无法搜索, 产品详情页面也打不开.

先看日志:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: java.util.SubList cannot be cast to java.util.LinkedList
         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
         at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:735)
         at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
         at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
         at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:643)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1374)
         at com.synnex.ecx.web.common.session.EcContextFilter.doFilter(EcContextFilter.java:92)
         at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
         at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at com.synnex.ecx.web.common.security.XssFilter.doFilter(XssFilter.java:26)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at com.synnex.cis.web.ext.filter.UrlSpyControlFilter.doFilter(UrlSpyControlFilter.java:138)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at com.synnex.jee.web.Log4JFilter.doFilter(Log4JFilter.java:54)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at com.synnex.cis.web.ext.filter.UrlSpyControlFilter.doFilterInner(UrlSpyControlFilter.java:563)
         at com.synnex.cis.web.ext.filter.GlobalUrlSpyControlFilter.doFilter(GlobalUrlSpyControlFilter.java:22)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at com.synnex.jee.web.PerformanceMeasurementFilter.doFilter(PerformanceMeasurementFilter.java:163)
         at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1345)
         at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:491)
         at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
         at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:486)
         at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:255)
         at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1067)
         at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:417)
         at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:216)
         at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1001)
         at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
         at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
         at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
         at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
         at org.eclipse.jetty.server.Server.handle(Server.java:360)
         at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
         at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890)
         at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944)
         at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:630)
         at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
         at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
         at org.eclipse.jetty.io.nio.SelectChanne

经过代码跟踪, 发现一段这样的可疑代码:

LinkedList<String> recentKeywords = (LinkedList<String>) map
      .get(PersonalizationMap.PREF_RECENTLY_SEARCHED_KEYWORDS);

此处, 从map中取出一个List, 强制转型为LinkedList. 但是, Map中取出的List对象预先做了截断处理.

         if (list.size() > VALUE_COUNT_LIMIT) {
            list = list.subList(0, VALUE_COUNT_LIMIT);
         }

 上面代码中的subList, 返回的对象其实是java.util.SubList, 所以转型失败.

究其原因, 是没有做到"基于接口编程", 其实没有必要强制转型为LinkedList, 转型为List就行了.

将代码稍作修改后, 问题解决. 如下:

List<String> recentKeywords = (List<String>) ecContext.getPref().get(
        PersonalizationMap.PREF_RECENTLY_SEARCHED_KEYWORDS);

猜你喜欢

转载自rickgong.iteye.com/blog/2204278