Author: bmaxwell
Date: 2011-04-20 19:23:27 -0400 (Wed, 20 Apr 2011)
New Revision: 1710
Modified:
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/javax/el/BeanELResolver.java
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/lang/ExpressionBuilder.java
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/util/ConcurrentCache.java
Log:
[JBPAPP-6381] fix Concurrent access to WeakHashMap in ConcurrentCache causes infinite
loop, 100% CPU usage
Property changes on: branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381
___________________________________________________________________
Added: svn:mergeinfo
+ /branches/JBOSSWEB_2_0_0_GA_CP:1574
Modified:
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/javax/el/BeanELResolver.java
===================================================================
---
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/javax/el/BeanELResolver.java 2011-04-20
23:19:41 UTC (rev 1709)
+++
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/javax/el/BeanELResolver.java 2011-04-20
23:23:27 UTC (rev 1710)
@@ -25,6 +25,8 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@@ -34,11 +36,30 @@
public class BeanELResolver extends ELResolver {
- private final boolean readOnly;
+ private static final int CACHE_SIZE;
+ private static final String CACHE_SIZE_PROP =
+ "org.apache.el.BeanELResolver.CACHE_SIZE";
- private final ConcurrentCache<String, BeanProperties> cache = new
ConcurrentCache<String, BeanProperties>(
- 1000);
+ static {
+ if (System.getSecurityManager() == null) {
+ CACHE_SIZE = Integer.parseInt(
+ System.getProperty(CACHE_SIZE_PROP, "1000"));
+ } else {
+ CACHE_SIZE = AccessController.doPrivileged(
+ new PrivilegedAction<Integer>() {
+ public Integer run() {
+ return Integer.valueOf(
+ System.getProperty(CACHE_SIZE_PROP, "1000"));
+ }
+ }).intValue();
+ }
+ }
+ private final boolean readOnly;
+
+ private final ConcurrentCache<String, BeanProperties> cache =
+ new ConcurrentCache<String, BeanProperties>(CACHE_SIZE);
+
public BeanELResolver() {
this.readOnly = false;
}
@@ -299,34 +320,37 @@
private final static class ConcurrentCache<K,V> {
- private final int size;
- private final Map<K,V> eden;
- private final Map<K,V> longterm;
-
- public ConcurrentCache(int size) {
- this.size = size;
- this.eden = new ConcurrentHashMap<K,V>(size);
- this.longterm = new WeakHashMap<K,V>(size);
- }
-
- public V get(K key) {
- V value = this.eden.get(key);
- if (value == null) {
- value = this.longterm.get(key);
- if (value != null) {
- this.eden.put(key, value);
- }
- }
- return value;
- }
-
- public void put(K key, V value) {
- if (this.eden.size() >= this.size) {
- this.longterm.putAll(this.eden);
- this.eden.clear();
- }
- this.eden.put(key, value);
- }
-
+ private final int size;
+ private final Map<K,V> eden;
+ private final Map<K,V> longterm;
+
+ public ConcurrentCache(int size) {
+ this.size = size;
+ this.eden = new ConcurrentHashMap<K,V>(size);
+ this.longterm = new WeakHashMap<K,V>(size);
+ }
+
+ public V get(K key) {
+ V value = this.eden.get(key);
+ if (value == null) {
+ synchronized (longterm) {
+ value = this.longterm.get(key);
+ }
+ if (value != null) {
+ this.eden.put(key, value);
+ }
+ }
+ return value;
+ }
+
+ public void put(K key, V value) {
+ if (this.eden.size() >= this.size) {
+ synchronized (longterm) {
+ this.longterm.putAll(this.eden);
+ }
+ this.eden.clear();
+ }
+ this.eden.put(key, value);
+ }
}
}
Modified:
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/lang/ExpressionBuilder.java
===================================================================
---
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/lang/ExpressionBuilder.java 2011-04-20
23:19:41 UTC (rev 1709)
+++
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/lang/ExpressionBuilder.java 2011-04-20
23:23:27 UTC (rev 1710)
@@ -19,6 +19,8 @@
import java.io.StringReader;
import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.el.ELContext;
import javax.el.ELException;
@@ -50,10 +52,30 @@
*/
public final class ExpressionBuilder implements NodeVisitor {
- private static final ConcurrentCache cache = new ConcurrentCache(5000);
+ private static final int CACHE_SIZE;
+ private static final String CACHE_SIZE_PROP =
+ "org.apache.el.ExpressionBuilder.CACHE_SIZE";
- private FunctionMapper fnMapper;
+ static {
+ if (System.getSecurityManager() == null) {
+ CACHE_SIZE = Integer.parseInt(
+ System.getProperty(CACHE_SIZE_PROP, "5000"));
+ } else {
+ CACHE_SIZE = AccessController.doPrivileged(
+ new PrivilegedAction<Integer>() {
+ public Integer run() {
+ return Integer.valueOf(
+ System.getProperty(CACHE_SIZE_PROP, "5000"));
+ }
+ }).intValue();
+ }
+ }
+ private static final ConcurrentCache<String, Node> cache =
+ new ConcurrentCache<String, Node>(CACHE_SIZE);
+
+ private FunctionMapper fnMapper;
+
private VariableMapper varMapper;
private String expression;
Modified:
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/util/ConcurrentCache.java
===================================================================
---
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/util/ConcurrentCache.java 2011-04-20
23:19:41 UTC (rev 1709)
+++
branches/JBOSSWEB_2_0_0_GA_CP05_JBPAPP-6381/src/share/classes/org/apache/el/util/ConcurrentCache.java 2011-04-20
23:23:27 UTC (rev 1710)
@@ -6,34 +6,38 @@
public final class ConcurrentCache<K,V> {
- private final int size;
-
- private final Map<K,V> eden;
-
- private final Map<K,V> longterm;
-
- public ConcurrentCache(int size) {
- this.size = size;
- this.eden = new ConcurrentHashMap<K,V>(size);
- this.longterm = new WeakHashMap<K,V>(size);
- }
-
- public V get(K k) {
- V v = this.eden.get(k);
- if (v == null) {
- v = this.longterm.get(k);
- if (v != null) {
- this.eden.put(k, v);
- }
- }
- return v;
- }
-
- public void put(K k, V v) {
- if (this.eden.size() >= size) {
- this.longterm.putAll(this.eden);
- this.eden.clear();
- }
- this.eden.put(k, v);
- }
+ private final int size;
+
+ private final Map<K,V> eden;
+
+ private final Map<K,V> longterm;
+
+ public ConcurrentCache(int size) {
+ this.size = size;
+ this.eden = new ConcurrentHashMap<K,V>(size);
+ this.longterm = new WeakHashMap<K,V>(size);
+ }
+
+ public V get(K k) {
+ V v = this.eden.get(k);
+ if (v == null) {
+ synchronized (longterm) {
+ v = this.longterm.get(k);
+ }
+ if (v != null) {
+ this.eden.put(k, v);
+ }
+ }
+ return v;
+ }
+
+ public void put(K k, V v) {
+ if (this.eden.size() >= size) {
+ synchronized (longterm) {
+ this.longterm.putAll(this.eden);
+ }
+ this.eden.clear();
+ }
+ this.eden.put(k, v);
+ }
}