title: How to avoid a huge query result causing an OutOfMemoryException
body: <p>Here's my situation:</p>
  
  <p>From my Grails controller, I call a service, which queries a database read-only, transforms the result into JSON, and returns the result.</p>
  
  <p>Specs are: JDK 1.6, Tomcat 5.5, Grails 1.3.4, DB via JNDI</p>
  
  <p>Tomcats MaxPermSize is set to 256m and Xmx to 128m.<br/>
  <strong>EDIT:</strong> Increasing the memory should be the last resort</p>
  
  <p>The service method:</p>
  
  <pre><code>  String queryDB(String queryString) {
      StringWriter writer = new StringWriter()
      JSonBuilder json = new JSonBuilder(writer)
      def queryResult = SomeDomain.findAllBySomePropIlike("%${queryString}%")
  
      json.whatever {
        results {
          queryResult.eachWithIndex { qr, i -&gt;
            // insert domain w/ properties
          }
        }
      }
      queryResult = null
      return writer.toString()
    }
  </code></pre>
  
  <p>Now, when queryString == 'a' the result set is huge and I end up with this: </p>
  
  <pre><code>[ERROR] 03/Nov/2010@09:46:39,604 [localhost].[/grails-app-0.1].[grails] - Servlet.service() for servlet grails threw exception
  java.lang.OutOfMemoryError: GC overhead limit exceeded
      at org.codehaus.groovy.util.ComplexKeyHashMap.init(ComplexKeyHashMap.java:81)
      at org.codehaus.groovy.util.ComplexKeyHashMap.&lt;init&gt;(ComplexKeyHashMap.java:46)
      at org.codehaus.groovy.util.SingleKeyHashMap.&lt;init&gt;(SingleKeyHashMap.java:29)
      at groovy.lang.MetaClassImpl$Index.&lt;init&gt;(MetaClassImpl.java:3381)
      at groovy.lang.MetaClassImpl$MethodIndex.&lt;init&gt;(MetaClassImpl.java:3364)
      at groovy.lang.MetaClassImpl.&lt;init&gt;(MetaClassImpl.java:140)
      at groovy.lang.MetaClassImpl.&lt;init&gt;(MetaClassImpl.java:190)
      at groovy.lang.MetaClassImpl.&lt;init&gt;(MetaClassImpl.java:196)
      at groovy.lang.ExpandoMetaClass.&lt;init&gt;(ExpandoMetaClass.java:298)
      at groovy.lang.ExpandoMetaClass.&lt;init&gt;(ExpandoMetaClass.java:333)
      at groovy.lang.ExpandoMetaClassCreationHandle.createNormalMetaClass(ExpandoMetaClassCreationHandle.java:46)
      at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:139)
      at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:122)
      at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:165)
      at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:182)
      at org.codehaus.groovy.runtime.callsite.ClassMetaClassGetPropertySite.&lt;init&gt;(ClassMetaClassGetPropertySite.java:35)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.createClassMetaClassGetPropertySite(AbstractCallSite.java:308)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.createGetPropertySite(AbstractCallSite.java:258)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.acceptGetProperty(AbstractCallSite.java:245)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:237)
      at org.codehaus.groovy.grails.plugins.web.filters.FilterToHandlerAdapter.accept(FilterToHandlerAdapter.groovy:196)
      at org.codehaus.groovy.grails.plugins.web.filters.FilterToHandlerAdapter$accept.callCurrent(Unknown Source)
      at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:143)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:159)
      at org.codehaus.groovy.grails.plugins.web.filters.FilterToHandlerAdapter.preHandle(FilterToHandlerAdapter.groovy:107)
      at org.springframework.web.servlet.HandlerInterceptor$preHandle.call(Unknown Source)
      at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
      at org.codehaus.groovy.grails.plugins.web.filters.CompositeInterceptor.preHandle(CompositeInterceptor.groovy:42)
      at org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet.doDispatch(GrailsDispatcherServlet.java:282)
  </code></pre>
  
  <p>One approach I found on the web regards some leaks in Hibernate and domain validation, explained <a href="http://grails.1312388.n4.nabble.com/Garbage-collection-td1585235.html" rel="nofollow">here</a> and in detail <a href="http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/" rel="nofollow">here</a>. I'm just about to test it, but I don't know if this is really the solution for my problem and (if it is) at which point it's best to clean up GORM.</p>
  
  <p>Or is there another memory leak in my code? 
  Ideas anyone?</p>
  
  <p><strong>EDIT:</strong> As far as I am now, the exception occurs at the point where the finder method is called. That means that GORM isn't able to handle the amount of data returned by the database, right? Sorry for asking like a greenhorn, but I have never encountered such a problem, even with very large result sets.</p>