I am using Velocity in a J2EE application. I had problems with my application leaking memory. I have traced this back to Velocity. I have made a little simple JUnit test, which demonstrates this memory leak. It seems that every time you instantiate a Velocity Engine with a resource loader it leaks about 1.5 Kb. If I do not include the setup of the resource loader from properties, there is no leak.
I found this in Velocity 1.3, but I have tried the same test with a cvs checkout of Velocity from today, and it showed the same problem. If I let the test run with a max heap size of 64Mb, it will fail with OutOfMemoryError exception after about 34.000 iterations.
I have attached the JUnit.


Cheers, Kim Madsen

/* Copyright (C) 1998-2002, Inceptor, Inc.  All rights reserved worldwide. */
package com.inceptor.rt;

import com.inceptor.base.ExceptionBase;
import com.inceptor.service.DiagnosticsFact;
import com.inceptor.service.DiagnosticsIf;
import com.inceptor.util.Test;
import com.inceptor.util.TestSuite;
import com.inceptor.util.TestCaseJUnit;
import com.inceptor.util.Various;

import java.io.StringWriter;
import java.util.Properties;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;

/** Servlet used to test <code>rt/Servlet</code> functionality.
 *
 * 
 * @version $Id: VelocityMemorySimple.java,v 1.3 2003/02/28 17:28:52 kim Exp $
 */
public class VelocityMemorySimple
    extends TestCaseJUnit {

    private static final DiagnosticsIf diag =
        DiagnosticsFact.instance(VelocityMemorySimple.class);

    private static final int ROWS_BETWEEN_DISPLAY = 1000;
    private static final int ROWS_TO_ITERATE = 50000 * ROWS_BETWEEN_DISPLAY;
    
    private static long lastTime = -1;

    public VelocityMemorySimple(String name) throws ExceptionBase {
        super(name);
    }

    ///////////////////////////////////////////////////////////////////

    private void showInfo(long rowsInserted)
        throws Exception {

        if (rowsInserted==0) {
            System.gc();
            lastTime = System.currentTimeMillis();
        }
        
        if (rowsInserted%ROWS_BETWEEN_DISPLAY == 0) {
            long nowTime = System.currentTimeMillis();
            System.gc();
            diag.info("Ite=" + rowsInserted
                      + " Mem free =" 
                      + java.lang.Runtime.getRuntime().freeMemory()
                      + " Mem total=" 
                      + java.lang.Runtime.getRuntime().totalMemory()
                      + " Ite/sec.="  
                      + ((double) 1000*ROWS_BETWEEN_DISPLAY)/(nowTime-lastTime)
                      );
            lastTime = nowTime;
        }
    }

    public void testMemory()
        throws Exception {

        try {
            Properties p = new Properties();
        
            p.setProperty("runtime.log.logsystem.class",
                          "org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
            p.setProperty("runtime.log.logsystem.log4j.category", "VELOCITY");
        
            p.setProperty("resource.manager.logwhenfound", "true");

            p.setProperty("velocimacro.library", "");

            p.setProperty("resource.loader",
                          "datasourceglobal, datasourcecustom");
            
            p.setProperty("datasourceglobal.resource.description",
                          "Load Templates From java:ExcediaDB Global Resources");
            p.setProperty("datasourceglobal.resource.loader.class",
                          
"org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader");
            p.setProperty("datasourceglobal.resource.loader.resource.datasource",
                          "java:ExcediaDB");
            p.setProperty("datasourceglobal.resource.loader.resource.table",
                          "RESOURCEGLOBALS");
            p.setProperty("datasourceglobal.resource.loader.resource.keycolumn",
                          "NAMESTR");
            p.setProperty("datasourceglobal.resource.loader.resource.templatecolumn",
                          "CONTENTCHARACTER");
            p.setProperty("datasourceglobal.resource.loader.resource.timestampcolumn",
                          "MODIFICATIONTIME");
            p.setProperty("datasourceglobal.resource.loader.resource.cache",
                          "true");
            p.setProperty("datasourceglobal.resource.loader.resource",
                          "6");
            
            p.setProperty("datasourcecustom.resource.description",
                          "Load Templates From java:ExcediaDB Custom Resources");
            p.setProperty("datasourcecustom.resource.loader.class",
                          
"org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader");
            p.setProperty("datasourcecustom.resource.loader.resource.datasource",
                          "java:ExcediaDB");
            p.setProperty("datasourcecustom.resource.loader.resource.table",
                          "RESOURCECUSTOMS");
            p.setProperty("datasourcecustom.resource.loader.resource.keycolumn",
                          "NAMESTR");
            p.setProperty("datasourcecustom.resource.loader.resource.templatecolumn",
                          "CONTENTCHARACTER");
            p.setProperty("datasourcecustom.resource.loader.resource.timestampcolumn",
                          "MODIFICATIONTIME");
            p.setProperty("datasourcecustom.resource.loader.resource.cache",
                          "true");
            p.setProperty("datasourcecustom.resource.loader.resource",
                          "6");
            VelocityContext context = null;
            StringWriter sw = null;
            VelocityEngine ve = null;


            for (int i=0; i<=ROWS_TO_ITERATE; i++) {
                showInfo(i);

                ve = new VelocityEngine();
                ve.init(p);
            }
        } catch (OutOfMemoryError e) {
            diag.error(e);
            throw e;
        }
    }

    public static Test suite() throws Exception {

        diag.debug("Setup test suite");
        TestSuite suite = new TestSuite();

        suite.addTest(new VelocityMemorySimple("testMemory"));

        return suite;
    }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to