Leaked object in FileResourceLoader#templatePaths
-------------------------------------------------
Key: VELOCITY-715
URL: https://issues.apache.org/jira/browse/VELOCITY-715
Project: Velocity
Issue Type: Bug
Components: Engine
Environment: Sun JRE 6 Update 13
Reporter: Atsushi Isobe
Priority: Minor
org.apache.velocity.runtime.resource.loader.FileResourceLoader#templatePaths
has stored templatename and real file path permanently.So if
VelocityEngine#getTemplate(String) has called by too many files, #templatePaths
have been enlarged.
Below my patch and test class.
---------------------------------------------------------------------------
---
./src/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java
(revision 772904)
+++
./src/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java
(working copy)
@@ -30,6 +30,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.WeakHashMap;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.exception.ResourceNotFoundException;
@@ -61,7 +62,7 @@
* times of the files. This is synchronizedMap
* instance.
*/
- private Map templatePaths = Collections.synchronizedMap(new HashMap());
+ private Map templatePaths = Collections.synchronizedMap(new WeakHashMap());
/** Shall we inspect unicode files to see what encoding they contain?. */
private boolean unicode = false;
@@ -330,8 +331,8 @@
currentFile = testFile;
}
}
- File file = getFile(path, fileName);
- if (currentFile == null || !file.exists())
+ File file = path != null ? getFile(path, fileName) : null;
+ if (currentFile == null || file == null || !file.exists())
{
/*
* noop: if the file is missing now (either the cached
@@ -365,6 +366,10 @@
public long getLastModified(Resource resource)
{
String path = (String) templatePaths.get(resource.getName());
+ if (path == null)
+ {
+ return 0;
+ }
File file = getFile(path, resource.getName());
if (file.canRead())
---------------------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.Properties;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
public class FileResourceLoaderLeakedObjectTest {
private static final String TEMPLATE_ENCODING = "UTF-8";
private static final File TEMPLATE_DIRECTORY = new File("./");
private static final String TEMPLATE_PREFIX = "testTemplate";
private static final String TEMPLATE_SUFFIX = ".vm";
private static final String TEMPLATE_STRING = "foobar";
private static final Log log =
LogFactory.getLog(FileResourceLoaderLeakedObjectTest.class);
public static void main(String[] args) throws Exception {
VelocityEngine ve = new VelocityEngine();
Properties properties = new Properties();
properties.put(Velocity.FILE_RESOURCE_LOADER_PATH,
TEMPLATE_DIRECTORY.getPath());
ve.init(properties);
VelocityContext context = new VelocityContext();
DecimalFormat countFormat = new DecimalFormat("000,000");
DecimalFormat totalFormat = new DecimalFormat("000,000,000");
StringWriter writer = new StringWriter();
File tmp = null;
for (int i = 0; i < 0x100000; i++) {
try {
tmp = File.createTempFile(TEMPLATE_PREFIX,
TEMPLATE_SUFFIX, TEMPLATE_DIRECTORY);
FileUtils.writeStringToFile(tmp,
TEMPLATE_STRING, TEMPLATE_ENCODING);
Template template =
ve.getTemplate(tmp.getPath(), TEMPLATE_ENCODING);
template.merge(context, writer);
if ((i & 0xFFFF) == 0) {
System.gc();
Runtime runtime = Runtime.getRuntime();
log.info(new StringBuilder("count:
").append(countFormat.format(i)).append(" total:
").append(totalFormat.format(runtime.totalMemory() - runtime.freeMemory())));
}
} catch (ResourceNotFoundException e) {
log.warn("", e);
} catch (ParseErrorException e) {
log.warn("", e);
} catch (MethodInvocationException e) {
log.warn("", e);
} catch (IOException e) {
log.warn("", e);
} catch (Exception e) {
log.warn("", e);
} finally {
if (tmp != null && tmp.exists()) {
tmp.delete();
}
}
}
}
}
---------------------------------------------------------------------------
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]