From 75bd998408dc23c051ea83fa09ea1be862c73397 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Tue, 29 Jan 2013 09:05:42 +0000 Subject: [PATCH] * cache compiled script snippets since each new instance leaks into PermGen memory --- .../filebot/format/ExpressionFormat.java | 19 ++++++++++++++++--- .../filebot/format/SecureCompiledScript.java | 9 ++++++--- .../filebot/ui/rename/BindingDialog.java | 5 ++--- .../filebot/format/ExpressionFormatTest.java | 3 +-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/source/net/sourceforge/filebot/format/ExpressionFormat.java b/source/net/sourceforge/filebot/format/ExpressionFormat.java index 8290c403..3ee58e19 100644 --- a/source/net/sourceforge/filebot/format/ExpressionFormat.java +++ b/source/net/sourceforge/filebot/format/ExpressionFormat.java @@ -13,7 +13,9 @@ import java.text.FieldPosition; import java.text.Format; import java.text.ParsePosition; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.script.Bindings; import javax.script.Compilable; @@ -30,6 +32,7 @@ import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; public class ExpressionFormat extends Format { private static ScriptEngine engine; + private static Map scriptletCache = new HashMap(); protected static synchronized ScriptEngine getGroovyScriptEngine() throws ScriptException { @@ -41,6 +44,16 @@ public class ExpressionFormat extends Format { } + protected static synchronized CompiledScript compileScriptlet(String expression) throws ScriptException { + Compilable engine = (Compilable) getGroovyScriptEngine(); + CompiledScript scriptlet = scriptletCache.get(expression); + if (scriptlet == null) { + scriptlet = engine.compile(expression); + scriptletCache.put(expression, scriptlet); + } + return scriptlet; + } + private final String expression; private final Object[] compilation; @@ -50,7 +63,7 @@ public class ExpressionFormat extends Format { public ExpressionFormat(String expression) throws ScriptException { this.expression = expression; - this.compilation = secure(compile(expression, (Compilable) getGroovyScriptEngine())); + this.compilation = secure(compile(expression)); } @@ -59,7 +72,7 @@ public class ExpressionFormat extends Format { } - protected Object[] compile(String expression, Compilable engine) throws ScriptException { + protected Object[] compile(String expression) throws ScriptException { List compilation = new ArrayList(); char open = '{'; @@ -87,7 +100,7 @@ public class ExpressionFormat extends Format { if (level == 1) { if (token.length() > 0) { try { - compilation.add(engine.compile(token.toString())); + compilation.add(compileScriptlet(token.toString())); } catch (ScriptException e) { // try to extract syntax exception ScriptException illegalSyntax = e; diff --git a/source/net/sourceforge/filebot/format/SecureCompiledScript.java b/source/net/sourceforge/filebot/format/SecureCompiledScript.java index 8ec1b17d..0014460d 100644 --- a/source/net/sourceforge/filebot/format/SecureCompiledScript.java +++ b/source/net/sourceforge/filebot/format/SecureCompiledScript.java @@ -36,13 +36,16 @@ public class SecureCompiledScript extends CompiledScript { permissions.add(new RuntimePermission("getFileSystemAttributes")); // write permissions for temp and cache folders - permissions.add(new FilePermission(new File(System.getProperty("ehcache.disk.store.dir")).getAbsolutePath() + File.separator + "-", "write, delete")); - permissions.add(new FilePermission(new File(System.getProperty("java.io.tmpdir")).getAbsolutePath() + File.separator + "-", "write, delete")); + try { + permissions.add(new FilePermission(new File(System.getProperty("java.io.tmpdir")).getAbsolutePath() + File.separator + "-", "write, delete")); + permissions.add(new FilePermission(new File(System.getProperty("ehcache.disk.store.dir")).getAbsolutePath() + File.separator + "-", "write, delete")); + } catch (Exception e) { + // ignore + } return permissions; } - private final CompiledScript compiledScript; private final AccessControlContext sandbox; diff --git a/source/net/sourceforge/filebot/ui/rename/BindingDialog.java b/source/net/sourceforge/filebot/ui/rename/BindingDialog.java index 2370569a..449ccd86 100644 --- a/source/net/sourceforge/filebot/ui/rename/BindingDialog.java +++ b/source/net/sourceforge/filebot/ui/rename/BindingDialog.java @@ -31,7 +31,6 @@ import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; -import javax.script.Compilable; import javax.script.ScriptException; import javax.swing.AbstractAction; import javax.swing.Action; @@ -432,9 +431,9 @@ class BindingDialog extends JDialog { ExpressionFormat format = new ExpressionFormat(expression) { @Override - protected Object[] compile(String expression, Compilable engine) throws ScriptException { + protected Object[] compile(String expression) throws ScriptException { // simple expression format, everything as one expression - return new Object[] { engine.compile(expression) }; + return new Object[] { compileScriptlet(expression) }; } }; diff --git a/test/net/sourceforge/filebot/format/ExpressionFormatTest.java b/test/net/sourceforge/filebot/format/ExpressionFormatTest.java index 6bb37680..17b4d6fd 100644 --- a/test/net/sourceforge/filebot/format/ExpressionFormatTest.java +++ b/test/net/sourceforge/filebot/format/ExpressionFormatTest.java @@ -5,7 +5,6 @@ package net.sourceforge.filebot.format; import static org.junit.Assert.*; import javax.script.Bindings; -import javax.script.Compilable; import javax.script.CompiledScript; import javax.script.ScriptException; import javax.script.SimpleBindings; @@ -19,7 +18,7 @@ public class ExpressionFormatTest { public void compile() throws Exception { ExpressionFormat format = new TestScriptFormat(""); - Object[] expression = format.compile("name: {name}, number: {number}", (Compilable) ExpressionFormat.getGroovyScriptEngine()); + Object[] expression = format.compile("name: {name}, number: {number}"); assertTrue(expression[0] instanceof String); assertTrue(expression[1] instanceof CompiledScript);