Uploaded image for project: 'Jira Data Center'
  1. Jira Data Center
  2. JRASERVER-28974

Search change HistoryFieldValueValidator can cause an OutOfMemoryError

    XMLWordPrintable

Details

    Description

      We had a SAC outage last night and this was due to the HistoryFieldValueValidator trying to find all possible values for the status field on SAC.

      This means it runs a query through the ChangeItem table for the field 'status'. In the code we use a DefaultOfBizListIterator (great) but then call getCompleteList() on it which loads everything from the result set into memory. This caused an OOME since on SAC there's ~2.2 million rows for the status field in the change item table (with 4 GB of heap).

      Here's the stacktrace from the heapdump:

      http-172.16.3.44-8080-134
        at java.nio.CharBuffer.wrap([CII)Ljava/nio/CharBuffer; (CharBuffer.java:350)
        at java.nio.CharBuffer.wrap([C)Ljava/nio/CharBuffer; (CharBuffer.java:373)
        at java.lang.StringCoding$StringDecoder.decode([BII)[C (StringCoding.java:138)
        at java.lang.StringCoding.decode(Ljava/lang/String;[BII)[C (StringCoding.java:173)
        at java.lang.String.<init>([BIILjava/lang/String;)V (String.java:443)
        at org.postgresql.core.Encoding.decode([BII)Ljava/lang/String; (Encoding.java:193)
        at org.postgresql.core.Encoding.decode([B)Ljava/lang/String; (Encoding.java:205)
        at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getString(I)Ljava/lang/String; (AbstractJdbc2ResultSet.java:1879)
        at org.apache.tomcat.dbcp.dbcp.DelegatingResultSet.getString(I)Ljava/lang/String; (DelegatingResultSet.java:175)
        at org.ofbiz.core.entity.jdbc.SqlJdbcUtil.getValue(Ljava/sql/ResultSet;ILorg/ofbiz/core/entity/model/ModelField;Lorg/ofbiz/core/entity/GenericEntity;Lorg/ofbiz/core/entity/model/ModelFieldTypeReader;)V (SqlJdbcUtil.java:529)
        at org.ofbiz.core.entity.EntityListIterator.currentGenericValue()Lorg/ofbiz/core/entity/GenericValue; (EntityListIterator.java:169)
        at org.ofbiz.core.entity.EntityListIterator.next()Lorg/ofbiz/core/entity/GenericValue; (EntityListIterator.java:246)
        at org.ofbiz.core.entity.EntityListIterator.getCompleteList()Ljava/util/List; (EntityListIterator.java:308)
        at com.atlassian.jira.ofbiz.DefaultOfBizListIterator.getCompleteList()Ljava/util/List; (DefaultOfBizListIterator.java:170)
        at com.atlassian.jira.issue.changehistory.DefaultChangeHistoryManager.getAllChangeItems(Ljava/lang/String;)Ljava/util/List; (DefaultChangeHistoryManager.java:285)
        at com.atlassian.jira.issue.changehistory.DefaultChangeHistoryManager.findAllPossibleValues(Ljava/lang/String;)Ljava/util/Map; (DefaultChangeHistoryManager.java:271)
        at com.atlassian.jira.jql.validator.HistoryFieldValueValidator.stringValueExists(Lcom/opensymphony/user/User;Ljava/lang/String;Ljava/lang/String;)Z (HistoryFieldValueValidator.java:69)
        at com.atlassian.jira.jql.validator.HistoryFieldValueValidator.validateValues(Lcom/opensymphony/user/User;Ljava/lang/String;Ljava/util/List;)Lcom/atlassian/jira/util/MessageSet; (HistoryFieldValueValidator.java:85)
        at com.atlassian.jira.jql.validator.HistoryPredicateValidator.validateTerminalPredicate(Lcom/atlassian/crowd/embedded/api/User;Lcom/atlassian/jira/util/I18nHelper;Lcom/atlassian/jira/util/MessageSet;Lcom/atlassian/query/history/TerminalHistoryPredicate;Ljava/lang/String;)V (HistoryPredicateValidator.java:95)
        at com.atlassian.jira.jql.validator.HistoryPredicateValidator.validate(Lcom/atlassian/query/history/HistoryPredicate;Ljava/lang/String;Lcom/atlassian/crowd/embedded/api/User;)Lcom/atlassian/jira/util/MessageSet; (HistoryPredicateValidator.java:69)
        at com.atlassian.jira.jql.validator.HistoryPredicateValidator.validate(Lcom/atlassian/crowd/embedded/api/User;Lcom/atlassian/query/clause/ChangedClause;Lcom/atlassian/query/history/HistoryPredicate;)Lcom/atlassian/jira/util/MessageSet; (HistoryPredicateValidator.java:58)
        at com.atlassian.jira.jql.validator.ChangedClauseValidator.validate(Lcom/atlassian/crowd/embedded/api/User;Lcom/atlassian/query/clause/ChangedClause;)Lcom/atlassian/jira/util/MessageSet; (ChangedClauseValidator.java:72)
        at com.atlassian.jira.jql.validator.ValidatorVisitor.visit(Lcom/atlassian/query/clause/ChangedClause;)Lcom/atlassian/jira/util/MessageSet; (ValidatorVisitor.java:118)
        at com.atlassian.jira.jql.validator.ValidatorVisitor.visit(Lcom/atlassian/query/clause/ChangedClause;)Ljava/lang/Object; (ValidatorVisitor.java:32)
        at com.atlassian.query.clause.ChangedClauseImpl.accept(Lcom/atlassian/query/clause/ClauseVisitor;)Ljava/lang/Object; (ChangedClauseImpl.java:73)
        at com.atlassian.jira.bc.issue.search.DefaultSearchService.validateQuery(Lcom/atlassian/crowd/embedded/api/User;Lcom/atlassian/query/Query;)Lcom/atlassian/jira/util/MessageSet; (DefaultSearchService.java:305)
        at com.atlassian.jira.bc.issue.search.DefaultSearchService.validateQuery(Lcom/opensymphony/user/User;Lcom/atlassian/query/Query;)Lcom/atlassian/jira/util/MessageSet; (DefaultSearchService.java:216)
        at com.atlassian.jira.web.action.issue.IssueNavigator.validateQuery(Lcom/atlassian/query/Query;)Z (IssueNavigator.java:848)
        at com.atlassian.jira.web.action.issue.IssueNavigator.updateSearchRequestWithJqlOrParams(Lcom/atlassian/jira/issue/search/SearchRequest;)V (IssueNavigator.java:691)
        at com.atlassian.jira.web.action.issue.IssueNavigator._doExecuteAdvanced()Ljava/lang/String; (IssueNavigator.java:594)
        at com.atlassian.jira.web.action.issue.IssueNavigator.doExecuteAdvanced()Ljava/lang/String; (IssueNavigator.java:544)
        at sun.reflect.GeneratedMethodAccessor3951.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (Method.java:597)
        at webwork.util.InjectionUtils$DefaultInjectionImpl.invoke(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (InjectionUtils.java:70)
        at webwork.util.InjectionUtils.invoke(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (InjectionUtils.java:56)
        at webwork.action.ActionSupport.invokeCommand()Ljava/lang/String; (ActionSupport.java:433)
        at webwork.action.ActionSupport.execute()Ljava/lang/String; (ActionSupport.java:157)
        at com.atlassian.jira.action.JiraActionSupport.execute()Ljava/lang/String; (JiraActionSupport.java:76)
        at webwork.interceptor.DefaultInterceptorChain.proceed()Ljava/lang/String; (DefaultInterceptorChain.java:39)
        at webwork.interceptor.NestedInterceptorChain.proceed()Ljava/lang/String; (NestedInterceptorChain.java:31)
        at webwork.interceptor.ChainedInterceptor.intercept(Lwebwork/interceptor/InterceptorChain;)Ljava/lang/String; (ChainedInterceptor.java:16)
        at webwork.interceptor.DefaultInterceptorChain.proceed()Ljava/lang/String; (DefaultInterceptorChain.java:35)
        at webwork.dispatcher.GenericDispatcher.executeAction(Lwebwork/action/Action;)Ljava/lang/String; (GenericDispatcher.java:205)
        at webwork.dispatcher.GenericDispatcher.executeAction()V (GenericDispatcher.java:143)
        at com.atlassian.jira.web.dispatcher.JiraWebworkActionDispatcher.service(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V (JiraWebworkActionDispatcher.java:152)
        at javax.servlet.http.HttpServlet.service(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:206)
        at com.atlassian.jira.web.filters.steps.ChainedFilterStepRunner.doFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;Ljavax/servlet/FilterChain;)V (ChainedFilterStepRunner.java:74)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V (ApplicationFilterChain.java:235)
      

      Attached a screenshot of the heap.

      Raising this as critical since this has the potential for huge support cost (heap dumps are hard to diagnose) and it's really quite easy to cause (the changeitem table is huge and only keeps growing over time). We really need to avoid loading unbounded tables fromt the DB into memory at all cost. In my mind that getCompleteList() method should be taken out the back and shot.

      Attachments

        Activity

          People

            edalgliesh Eric Dalgliesh
            andreask@atlassian.com Andreas Knecht (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: