You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by sc...@apache.org on 2008/04/21 17:42:35 UTC
svn commit: r650177 - in
/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2:
datasource/jaxb/JAXBDSContext.java jaxws/message/databinding/JAXBUtils.java
Author: scheu
Date: Mon Apr 21 08:42:32 2008
New Revision: 650177
URL: http://svn.apache.org/viewvc?rev=650177&view=rev
Log:
AXIS2-3758
Contributor:Rich Scheuerle
Use WeakReference objects to allow gc() to reclaim JAXBContext and related objects.
Modified:
webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java
webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java
Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java?rev=650177&r1=650176&r2=650177&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/datasource/jaxb/JAXBDSContext.java Mon Apr 21 08:42:32 2008
@@ -45,6 +45,7 @@
import javax.xml.ws.Holder;
import javax.xml.ws.WebServiceException;
import java.io.OutputStream;
+import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.PrivilegedAction;
@@ -64,17 +65,22 @@
public static final boolean DEBUG_ENABLED = log.isDebugEnabled();
private TreeSet<String> contextPackages; // List of packages needed by the context
- private String contextPackagesKey; // Unique key that represents the set of contextPackages (usually toString)
- private JAXBContext jaxbContext = null; // JAXBContext
+ private String contextPackagesKey; // Unique key that represents the set of packages
+
+ private JAXBContext customerJAXBContext; // JAXBContext provided by the customer api
+ // JAXBContext loaded by the engine. It is weakref'd to allow GC
+ private WeakReference<JAXBContext> autoJAXBContext = null;
private JAXBUtils.CONSTRUCTION_TYPE // How the JAXBContext is constructed
constructionType = JAXBUtils.CONSTRUCTION_TYPE.UNKNOWN;
private MessageContext msgContext;
- // There are two modes of marshalling and unmarshalling: "by java type" and "by schema element".
+ // There are two modes of marshalling and unmarshalling:
+ // "by java type" and "by schema element".
// The prefered mode is "by schema element" because it is safe and xml-centric.
// However there are some circumstances when "by schema element" is not available.
// Examples: RPC Lit processing (the wire element is defined by a wsdl:part...not schema)
- // Doc/Lit Bare "Minimal" Processing (JAXB ObjectFactories are missing...and thus we must use "by type" for primitives/String)
+ // Doc/Lit Bare "Minimal" Processing (JAXB ObjectFactories are missing...
+ // and thus we must use "by type" for primitives/String)
// Please don't use "by java type" processing to get around errors.
private Class processType = null;
private boolean isxmlList =false;
@@ -111,13 +117,14 @@
}
/**
- * "Dispatch" Constructor Use this full constructor when the JAXBContent is provided by the
+ * "Dispatch" Constructor
+ * Use this full constructor when the JAXBContent is provided by the
* customer.
*
* @param jaxbContext
*/
public JAXBDSContext(JAXBContext jaxbContext) {
- this.jaxbContext = jaxbContext;
+ this.customerJAXBContext = jaxbContext;
}
/** @return Class representing type of the element */
@@ -134,22 +141,33 @@
* @throws JAXBException
*/
public JAXBContext getJAXBContext(ClassLoader cl) throws JAXBException {
- if (jaxbContext == null) {
+ if (customerJAXBContext != null) {
+ return customerJAXBContext;
+ }
+
+ // Get the weakly cached JAXBContext
+ JAXBContext jc = null;
+ if (autoJAXBContext != null) {
+ jc = autoJAXBContext.get();
+ }
+
+ if (jc == null) {
if (log.isDebugEnabled()) {
log.debug(
"A JAXBContext did not exist, creating a new one with the context packages.");
}
Holder<JAXBUtils.CONSTRUCTION_TYPE> constructType =
new Holder<JAXBUtils.CONSTRUCTION_TYPE>();
- jaxbContext =
+ jc =
JAXBUtils.getJAXBContext(contextPackages, constructType, contextPackagesKey, cl);
constructionType = constructType.value;
+ autoJAXBContext = new WeakReference<JAXBContext>(jc);
} else {
if (log.isDebugEnabled()) {
log.debug("Using an existing JAXBContext");
}
}
- return jaxbContext;
+ return jc;
}
/** @return RPC Declared Type */
Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java?rev=650177&r1=650176&r2=650177&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java Mon Apr 21 08:42:32 2008
@@ -59,9 +59,15 @@
private static final Log log = LogFactory.getLog(JAXBUtils.class);
- // Create a concurrent map to get the JAXBObject: keys are ClassLoader and String (package names).
- private static Map<ClassLoader, Map<String, JAXBContextValue>> jaxbMap =
- new ConcurrentHashMap<ClassLoader, Map<String, JAXBContextValue>>();
+ // Create a concurrent map to get the JAXBObject:
+ // key is the String (sorted packages)
+ // value is a WeakReference to a ConcurrentHashMap of Classloader keys and JAXBContextValue objects
+ // It is a weak map to encourage GC in low memory situations
+ private static Map<
+ String,
+ WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>> jaxbMap =
+ new ConcurrentHashMap<String,
+ WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>>();
private static Pool<JAXBContext, Marshaller> mpool = new Pool<JAXBContext, Marshaller>();
private static Pool<JAXBContext, Unmarshaller> upool = new Pool<JAXBContext, Unmarshaller>();
@@ -151,59 +157,115 @@
}
}
JAXBUtilsMonitor.addPackageKey(key);
-
- // The JAXBContexts are keyed by ClassLoader and the set of Strings
- ClassLoader cl = getContextClassLoader();
- // Get the innerMap
- Map<String, JAXBContextValue> innerMap = null;
- innerMap = getInnerMap(cacheKey, cl);
+ // Get or Create The InnerMap using the package key
+ ConcurrentHashMap<ClassLoader, JAXBContextValue> innerMap = null;
+ WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>
+ weakRef = jaxbMap.get(key);
+
+ if (weakRef != null) {
+ innerMap = weakRef.get();
+ }
+
if (innerMap == null) {
synchronized(jaxbMap) {
- innerMap = getInnerMap(cacheKey, cl);
- if(innerMap==null) {
- adjustPoolSize(jaxbMap);
- innerMap = new ConcurrentHashMap<String, JAXBContextValue>();
- if (cacheKey != null) {
- jaxbMap.put(cacheKey, innerMap);
- }
+ weakRef = jaxbMap.get(key);
+ if (weakRef != null) {
+ innerMap = weakRef.get();
+ }
+ if (innerMap == null) {
+ innerMap = new ConcurrentHashMap<ClassLoader, JAXBContextValue>();
+ weakRef =
+ new WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>(innerMap);
+ jaxbMap.put(key, weakRef);
}
}
}
+
+ // Now get the contextValue using either the classloader key or
+ // the current Classloader
+ ClassLoader cl = getContextClassLoader();
+ JAXBContextValue contextValue = null;
+ if(cacheKey != null) {
+ if(log.isDebugEnabled()) {
+ log.debug("Using supplied classloader to retrieve JAXBContext: " +
+ cacheKey);
+ }
+ contextValue = innerMap.get(cacheKey);
+ } else {
+ if(log.isDebugEnabled()) {
+ log.debug("Using classloader from Thread to retrieve JAXBContext: " +
+ cl);
+ }
+ contextValue = innerMap.get(cl);
+ }
+
+
if (contextPackages == null) {
contextPackages = new TreeSet<String>();
}
-
- JAXBContextValue contextValue = innerMap.get(key);
if (contextValue == null) {
synchronized (innerMap) {
- contextValue = innerMap.get(key);
- if(contextValue==null) {
- adjustPoolSize(innerMap);
-
+ // Try to get the contextValue once more since sync was temporarily exited.
+ ClassLoader clKey = (cacheKey != null) ? cacheKey:cl;
+ contextValue = innerMap.get(clKey);
+ adjustPoolSize(innerMap);
+ if (contextValue==null) {
// Create a copy of the contextPackages. This new TreeSet will
// contain only the valid contextPackages.
// Note: The original contextPackage set is accessed by multiple
// threads and should not be altered.
- TreeSet<String> validContextPackages = new TreeSet<String>(contextPackages);
+ TreeSet<String> validContextPackages = new TreeSet<String>(contextPackages);
+
+ ClassLoader tryCl = cl;
contextValue = createJAXBContextValue(validContextPackages, cl);
// If we don't get all the classes, try the cached classloader
if (cacheKey != null && validContextPackages.size() != contextPackages.size()) {
+ tryCl = cacheKey;
validContextPackages = new TreeSet<String>(contextPackages);
contextValue = createJAXBContextValue(validContextPackages, cacheKey);
}
+ synchronized (jaxbMap) {
+ // Add the context value with the original package set
+ ConcurrentHashMap<ClassLoader, JAXBContextValue> map1 = null;
+ WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>
+ weakRef1 = jaxbMap.get(key);
+ if (weakRef1 != null) {
+ map1 = weakRef.get();
+ }
+ if (map1 == null) {
+ map1 = new ConcurrentHashMap<ClassLoader, JAXBContextValue>();
+ weakRef1 =
+ new WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>(map1);
+ jaxbMap.put(key, weakRef1);
+ }
+ map1.put(clKey, contextValue);
- // Put the new context in the map keyed by both the original and valid list of packages
- String validPackagesKey = validContextPackages.toString();
- innerMap.put(key, contextValue);
- innerMap.put(validPackagesKey, contextValue);
- if (log.isDebugEnabled()) {
- log.debug("JAXBContext [created] for " + key);
- log.debug("JAXBContext also stored by the list of valid packages:" + validPackagesKey);
- }
+ String validPackagesKey = validContextPackages.toString();
+
+ // Add the context value with the new package set
+ ConcurrentHashMap<ClassLoader, JAXBContextValue> map2 = null;
+ WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>
+ weakRef2 = jaxbMap.get(validPackagesKey);
+ if (weakRef2 != null) {
+ map2 = weakRef.get();
+ }
+ if (map2 == null) {
+ map2 = new ConcurrentHashMap<ClassLoader, JAXBContextValue>();
+ weakRef2 =
+ new WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>>(map2);
+ jaxbMap.put(key, weakRef2);
+ }
+ map2.put(clKey, contextValue);
+
+ if (log.isDebugEnabled()) {
+ log.debug("JAXBContext [created] for " + key);
+ log.debug("JAXBContext also stored by the list of valid packages:" + validPackagesKey);
+ }
+ }
}
}
} else {
@@ -215,24 +277,6 @@
return contextValue.jaxbContext;
}
- private static Map<String, JAXBContextValue> getInnerMap(ClassLoader cacheKey, ClassLoader cl) {
- Map<String, JAXBContextValue> innerMap;
- if(cacheKey != null) {
- if(log.isDebugEnabled()) {
- log.debug("Using supplied classloader to retrieve JAXBContext: " +
- cacheKey);
- }
- innerMap = jaxbMap.get(cacheKey);
- }else {
- if(log.isDebugEnabled()) {
- log.debug("Using classloader from Thread to retrieve JAXBContext: " +
- cl);
- }
- innerMap = jaxbMap.get(cl);
- }
- return innerMap;
- }
-
/**
* Create a JAXBContext using the contextPackages
*
@@ -354,9 +398,15 @@
// The code above may have removed some packages from the list.
// Retry our lookup with the updated list
- Map<String, JAXBContextValue> innerMap = jaxbMap.get(cl);
+ String key = contextPackages.toString();
+ ConcurrentHashMap<ClassLoader, JAXBContextValue> innerMap = null;
+ WeakReference<ConcurrentHashMap<ClassLoader, JAXBContextValue>> weakRef = jaxbMap.get(key);
+ if (weakRef != null) {
+ innerMap = weakRef.get();
+ }
+
if (innerMap != null) {
- contextValue = innerMap.get(contextPackages.toString());
+ contextValue = innerMap.get(cl);
if (contextValue != null) {
if (log.isDebugEnabled()) {
log.debug("Successfully found JAXBContext with updated context list:" +
@@ -1012,7 +1062,9 @@
* @param <V> Pooled object
*/
private static class Pool<K,V> {
- private Map<K,List<WeakReference<V>>> map = new ConcurrentHashMap<K, List<WeakReference<V>>>();
+ private WeakReference<Map<K,List<V>>> weakMap =
+ new WeakReference<Map<K,List<V>>>(
+ new ConcurrentHashMap<K, List<V>>());
// The maps are freed up when a LOAD FACTOR is hit
private static int MAX_LIST_FACTOR = 10;
@@ -1022,16 +1074,12 @@
* @return removed item from pool or null.
*/
public V get(K key) {
- List<WeakReference<V>> values = getValues(key);
+ List<V> values = getValues(key);
synchronized (values) {
- while (values.size()>0) {
- // Get the WeakReference, and return the actual value if it is not
- // GC'd. Otherwise try the next WeakReference
- WeakReference<V> wr = values.remove(values.size()-1);
- V v = wr.get();
- if (v != null) {
- return v;
- }
+ if (values.size()>0) {
+ V v = values.remove(values.size()-1);
+ return v;
+
}
}
return null;
@@ -1044,12 +1092,10 @@
*/
public void put(K key, V value) {
adjustSize();
- List<WeakReference<V>> values = getValues(key);
+ List<V> values = getValues(key);
synchronized (values) {
if (values.size() < MAX_LIST_FACTOR) {
- // Add a WeakReference to the value so that it can be GC'd
- WeakReference<V> wr = new WeakReference<V>(value);
- values.add(wr);
+ values.add(value);
}
}
}
@@ -1059,16 +1105,28 @@
* @param key
* @return list of values.
*/
- private List<WeakReference<V>> getValues(K key) {
- List<WeakReference<V>> values = map.get(key);
- if(values !=null) {
- return values;
+ private List<V> getValues(K key) {
+ Map<K,List<V>> map = weakMap.get();
+ List<V> values = null;
+ if (map != null) {
+ values = map.get(key);
+ if(values !=null) {
+ return values;
+ }
}
synchronized (this) {
- values = map.get(key);
- if(values==null) {
- values = new ArrayList<WeakReference<V>>();
+ if (map != null) {
+ values = map.get(key);
+ }
+ if (values == null) {
+ if (map == null) {
+ map = new ConcurrentHashMap<K, List<V>>();
+ weakMap =
+ new WeakReference<Map<K,List<V>>>(map);
+ }
+ values = new ArrayList<V>();
map.put(key, values);
+
}
return values;
}
@@ -1083,7 +1141,8 @@
* a large footprint.
*/
private void adjustSize() {
- if (map.size() > MAX_LOAD_FACTOR) {
+ Map<K,List<V>> map = weakMap.get();
+ if (map != null && map.size() > MAX_LOAD_FACTOR) {
// Remove every other Entry in the map.
Iterator it = map.entrySet().iterator();
boolean removeIt = false;
---------------------------------------------------------------------
To unsubscribe, e-mail: axis-cvs-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-cvs-help@ws.apache.org