[Jython-checkins] jython: Issue1746 - Fix issue with static codecs causing out of PermGen memory errors

frank.wierzbicki jython-checkins at python.org
Sat Sep 21 03:00:49 CEST 2013


http://hg.python.org/jython/rev/7ff23feeb526
changeset:   7126:7ff23feeb526
user:        Brandon Pedersen <bpedman at gmail.com>
date:        Fri Sep 20 18:00:18 2013 -0700
summary:
  Issue1746 - Fix issue with static codecs causing out of PermGen memory errors

files:
  ACKNOWLEDGMENTS                        |    1 +
  src/org/python/core/PySystemState.java |   16 +
  src/org/python/core/codecs.java        |  178 ++++++------
  3 files changed, 109 insertions(+), 86 deletions(-)


diff --git a/ACKNOWLEDGMENTS b/ACKNOWLEDGMENTS
--- a/ACKNOWLEDGMENTS
+++ b/ACKNOWLEDGMENTS
@@ -103,6 +103,7 @@
     Christian Klein
     Jezreel Ng
     Santoso Wijaya
+    Brandon Pedersen
 
 Local Variables:
 mode: indented-text
diff --git a/src/org/python/core/PySystemState.java b/src/org/python/core/PySystemState.java
--- a/src/org/python/core/PySystemState.java
+++ b/src/org/python/core/PySystemState.java
@@ -166,6 +166,8 @@
 
     private int recursionlimit = 1000;
 
+    private codecs.CodecState codecState;
+
     /** true when a SystemRestart is triggered. */
     public boolean _systemRestart = false;
 
@@ -342,6 +344,20 @@
         }
     }
 
+    public synchronized codecs.CodecState getCodecState() {
+        if (codecState == null) {
+            codecState = new codecs.CodecState();
+            try {
+                imp.load("encodings");
+            } catch (PyException exc) {
+                if (exc.type != Py.ImportError) {
+                    throw exc;
+                }
+            }
+        }
+        return codecState;
+    }
+
     // xxx fix this accessors
     @Override
     public PyObject __findattr_ex__(String name) {
diff --git a/src/org/python/core/codecs.java b/src/org/python/core/codecs.java
--- a/src/org/python/core/codecs.java
+++ b/src/org/python/core/codecs.java
@@ -33,97 +33,35 @@
     public static final String REPLACE = "replace";
     public static final String XMLCHARREFREPLACE = "xmlcharrefreplace";
     private static char Py_UNICODE_REPLACEMENT_CHARACTER = 0xFFFD;
-    private static PyList searchPath;
-    private static PyStringMap searchCache;
-    private static PyStringMap errorHandlers;
-    /** Used to synchronize registry_init. */
-    private static final Object INIT_LOCK = new Object();
-    private static String default_encoding = "ascii";
 
     public static String getDefaultEncoding() {
-        return default_encoding;
+        return Py.getSystemState().getCodecState().getDefaultEncoding();
     }
 
     public static void setDefaultEncoding(String encoding) {
-        lookup(encoding);
-        default_encoding = encoding;
+        Py.getSystemState().getCodecState().setDefaultEncoding(encoding);
     }
 
     public static PyObject lookup_error(String handlerName) {
-        registry_init();
-        if (handlerName == null) {
-            handlerName = "strict";
-        }
-        PyObject handler = errorHandlers.__finditem__(handlerName.intern());
-        if (handler == null) {
-            throw new PyException(Py.LookupError, "unknown error handler name '" + handlerName
-                    + "'");
-        }
-        return handler;
+        return Py.getSystemState().getCodecState().lookup_error(handlerName);
     }
 
     public static void register_error(String name, PyObject error) {
-        registry_init();
-        if (!error.isCallable()) {
-            throw Py.TypeError("argument must be callable");
-        }
-        errorHandlers.__setitem__(name.intern(), error);
+        Py.getSystemState().getCodecState().register_error(name, error);
     }
 
     public static void register(PyObject search_function) {
-        registry_init();
-        if (!search_function.isCallable()) {
-            throw Py.TypeError("argument must be callable");
-        }
-        searchPath.append(search_function);
+        Py.getSystemState().getCodecState().register(search_function);
     }
 
     public static PyTuple lookup(String encoding) {
-        registry_init();
-        PyString v = new PyString(normalizestring(encoding));
-        PyObject cached = searchCache.__finditem__(v);
-        if (cached != null) {
-            return (PyTuple)cached;
-        }
-
-        if (searchPath.__len__() == 0) {
-            throw new PyException(Py.LookupError,
-                    "no codec search functions registered: can't find encoding '" + encoding + "'");
-        }
-
-        for (PyObject func : searchPath.asIterable()) {
-            PyObject created = func.__call__(v);
-            if (created == Py.None) {
-                continue;
-            }
-            if (!(created instanceof PyTuple) || created.__len__() != 4) {
-                throw Py.TypeError("codec search functions must return 4-tuples");
-            }
-            searchCache.__setitem__(v, created);
-            return (PyTuple)created;
-        }
-        throw new PyException(Py.LookupError, "unknown encoding '" + encoding + "'");
+        return Py.getSystemState().getCodecState().lookup(encoding);
     }
 
     private static String normalizestring(String string) {
         return string.toLowerCase().replace(' ', '-');
     }
 
-    private static boolean import_encodings_called;
-
-    private static void import_encodings() {
-        if (!import_encodings_called) {
-            import_encodings_called = true;
-            try {
-                imp.load("encodings");
-            } catch (PyException exc) {
-                if (exc.type != Py.ImportError) {
-                    throw exc;
-                }
-            }
-        }
-    }
-
     /**
      * Decode the bytes <code>v</code> using the codec registered for the <code>encoding</code>.
      * The <code>encoding</code> defaults to the system default encoding
@@ -422,24 +360,6 @@
         }
     }
 
-    private static void registry_init() {
-        synchronized (INIT_LOCK) {
-            if (searchPath != null) {
-                return;
-            }
-            searchPath = new PyList();
-            searchCache = new PyStringMap();
-            errorHandlers = new PyStringMap();
-            String[] builtinErrorHandlers =
-                    new String[] {"strict", IGNORE, REPLACE, XMLCHARREFREPLACE, BACKSLASHREPLACE};
-            for (String builtinErrorHandler : builtinErrorHandlers) {
-                register_error(builtinErrorHandler,
-                        Py.newJavaFunc(codecs.class, builtinErrorHandler + "_errors"));
-            }
-            import_encodings();
-        }
-    }
-
     /* --- UTF-7 Codec -------------------------------------------------------- */
 
     /*
@@ -1723,6 +1643,92 @@
         }
         return newPosition;
     }
+
+    public static class CodecState {
+        private PyList searchPath;
+        private PyStringMap searchCache;
+        private PyStringMap errorHandlers;
+        private String default_encoding = "ascii";
+
+        public static final String[] BUILTIN_ERROR_HANDLERS = new String[]{"strict",
+                IGNORE,
+                REPLACE,
+                XMLCHARREFREPLACE,
+                BACKSLASHREPLACE
+        };
+
+        public CodecState() {
+            searchPath = new PyList();
+            searchCache = new PyStringMap();
+            errorHandlers = new PyStringMap();
+
+            for (String builtinErrorHandler : BUILTIN_ERROR_HANDLERS) {
+                register_error(builtinErrorHandler, Py.newJavaFunc(codecs.class,
+                        builtinErrorHandler + "_errors"));
+            }
+        }
+
+        public String getDefaultEncoding() {
+            return default_encoding;
+        }
+
+        public void setDefaultEncoding(String encoding) {
+            lookup(encoding);
+            default_encoding = encoding;
+        }
+
+        public void register_error(String name, PyObject error) {
+            if (!error.isCallable()) {
+                throw Py.TypeError("argument must be callable");
+            }
+            errorHandlers.__setitem__(name.intern(), error);
+        }
+
+        public void register(PyObject search_function) {
+            if (!search_function.isCallable()) {
+                throw Py.TypeError("argument must be callable");
+            }
+            searchPath.append(search_function);
+        }
+
+        public PyTuple lookup(String encoding) {
+            PyString v = new PyString(normalizestring(encoding));
+            PyObject cached = searchCache.__finditem__(v);
+            if (cached != null) {
+                return (PyTuple)cached;
+            }
+
+            if (searchPath.__len__() == 0) {
+                throw new PyException(Py.LookupError,
+                        "no codec search functions registered: can't find encoding '" + encoding + "'");
+            }
+
+            for (PyObject func : searchPath.asIterable()) {
+                PyObject created = func.__call__(v);
+                if (created == Py.None) {
+                    continue;
+                }
+                if (!(created instanceof PyTuple) || created.__len__() != 4) {
+                    throw Py.TypeError("codec search functions must return 4-tuples");
+                }
+                searchCache.__setitem__(v, created);
+                return (PyTuple)created;
+            }
+            throw new PyException(Py.LookupError, "unknown encoding '" + encoding + "'");
+        }
+
+        public PyObject lookup_error(String handlerName) {
+            if (handlerName == null) {
+                handlerName = "strict";
+            }
+            PyObject handler = errorHandlers.__finditem__(handlerName.intern());
+            if (handler == null) {
+                throw new PyException(Py.LookupError,
+                        "unknown error handler name '" + handlerName + "'");
+            }
+            return handler;
+        }
+    }
 }
 
 

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list