From b858fab8d7cd58971dc22f9b4b1d86c260054339 Mon Sep 17 00:00:00 2001 From: alepar Date: Tue, 22 Nov 2011 15:50:52 +0400 Subject: [PATCH 1/9] loadClass() already queries the cache, so no point in redoing it in resolveClass() --- .../serialization/CompactObjectInputStream.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java index c3f1afe557..a3e2c9dbe7 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java @@ -77,21 +77,13 @@ class CompactObjectInputStream extends ObjectInputStream { @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - // Query the cache first. - String className = desc.getName(); - Class clazz = classCache.get(className); - if (clazz != null) { - return clazz; - } - - // And then try to resolve. + Class clazz; try { - clazz = loadClass(className); + clazz = loadClass(desc.getName()); } catch (ClassNotFoundException ex) { clazz = super.resolveClass(desc); } - classCache.put(className, clazz); return clazz; } From dd567e059f6d45361c4cf2734bbf670daf6f6d32 Mon Sep 17 00:00:00 2001 From: alepar Date: Tue, 22 Nov 2011 15:51:14 +0400 Subject: [PATCH 2/9] there's a more general exception in the throws list already --- .../handler/codec/serialization/CompactObjectInputStream.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java index a3e2c9dbe7..27fd6f2ada 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java @@ -46,8 +46,7 @@ class CompactObjectInputStream extends ObjectInputStream { } @Override - protected void readStreamHeader() throws IOException, - StreamCorruptedException { + protected void readStreamHeader() throws IOException { int version = readByte() & 0xFF; if (version != STREAM_VERSION) { throw new StreamCorruptedException( From c7cea76d2fb550507f87fd350bd731cbb6929f08 Mon Sep 17 00:00:00 2001 From: alepar Date: Tue, 22 Nov 2011 15:54:59 +0400 Subject: [PATCH 3/9] moving classLoader selection to constructor --- .../CompactObjectInputStream.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java index 27fd6f2ada..95c9eccec0 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java @@ -42,7 +42,11 @@ class CompactObjectInputStream extends ObjectInputStream { CompactObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException { super(in); - this.classLoader = classLoader; + if (classLoader == null) { + this.classLoader = defaultClassLoader(); + } else { + this.classLoader = classLoader; + } } @Override @@ -95,18 +99,19 @@ class CompactObjectInputStream extends ObjectInputStream { } // And then try to load. - ClassLoader classLoader = this.classLoader; - if (classLoader == null) { - classLoader = Thread.currentThread().getContextClassLoader(); - } - - if (classLoader != null) { - clazz = classLoader.loadClass(className); - } else { - clazz = Class.forName(className); - } + clazz = classLoader.loadClass(className); classCache.put(className, clazz); return clazz; } + + private static ClassLoader defaultClassLoader() { + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + if (contextClassLoader != null) { + return contextClassLoader; + } + + return CompactObjectInputStream.class.getClassLoader(); + } + } From deb61aa0219af6693c18b702d93a0ed57d4cd4ed Mon Sep 17 00:00:00 2001 From: alepar Date: Tue, 22 Nov 2011 17:33:54 +0400 Subject: [PATCH 4/9] extracting class resolving role to separate interface --- .../serialization/CachingClassResolver.java | 31 ++++++++++++ .../codec/serialization/ClassResolver.java | 7 +++ .../codec/serialization/ClassResolvers.java | 24 ++++++++++ .../ClassloaderClassResolver.java | 16 +++++++ .../CompactObjectInputStream.java | 47 +++---------------- .../codec/serialization/ObjectDecoder.java | 12 ++--- .../ObjectDecoderInputStream.java | 2 +- 7 files changed, 91 insertions(+), 48 deletions(-) create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java new file mode 100644 index 0000000000..93524d5438 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CachingClassResolver.java @@ -0,0 +1,31 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.util.Map; + +class CachingClassResolver implements ClassResolver { + + private final Map> classCache; + private final ClassResolver delegate; + + CachingClassResolver(ClassResolver delegate, Map> classCache) { + this.delegate = delegate; + this.classCache = classCache; + } + + @Override + public Class resolve(String className) throws ClassNotFoundException { + // Query the cache first. + Class clazz; + clazz = classCache.get(className); + if (clazz != null) { + return clazz; + } + + // And then try to load. + clazz = delegate.resolve(className); + + classCache.put(className, clazz); + return clazz; + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java new file mode 100644 index 0000000000..a6fa1c52d7 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java @@ -0,0 +1,7 @@ +package org.jboss.netty.handler.codec.serialization; + +interface ClassResolver { + + Class resolve(String className) throws ClassNotFoundException; + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java new file mode 100644 index 0000000000..e802838080 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java @@ -0,0 +1,24 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.util.HashMap; + +public class ClassResolvers { + + public static ClassResolver cachingResolver(ClassLoader classLoader) { + if (classLoader == null) { + classLoader = defaultClassLoader(); + } + + return new CachingClassResolver(new ClassloaderClassResolver(classLoader), new HashMap>()); + } + + static ClassLoader defaultClassLoader() { + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + if (contextClassLoader != null) { + return contextClassLoader; + } + + return CompactObjectInputStream.class.getClassLoader(); + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java new file mode 100644 index 0000000000..545e8e3f08 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java @@ -0,0 +1,16 @@ +package org.jboss.netty.handler.codec.serialization; + +class ClassloaderClassResolver implements ClassResolver { + + private final ClassLoader classLoader; + + ClassloaderClassResolver(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public Class resolve(String className) throws ClassNotFoundException { + return classLoader.loadClass(className); + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java index 95c9eccec0..2ced2188d4 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/CompactObjectInputStream.java @@ -21,8 +21,6 @@ import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.StreamCorruptedException; -import java.util.HashMap; -import java.util.Map; /** * @author The Netty Project @@ -32,21 +30,12 @@ import java.util.Map; * */ class CompactObjectInputStream extends ObjectInputStream { + + private final ClassResolver classResolver; - private final Map> classCache = new HashMap>(); - private final ClassLoader classLoader; - - CompactObjectInputStream(InputStream in) throws IOException { - this(in, null); - } - - CompactObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException { + CompactObjectInputStream(InputStream in, ClassResolver classResolver) throws IOException { super(in); - if (classLoader == null) { - this.classLoader = defaultClassLoader(); - } else { - this.classLoader = classLoader; - } + this.classResolver = classResolver; } @Override @@ -70,7 +59,7 @@ class CompactObjectInputStream extends ObjectInputStream { return super.readClassDescriptor(); case CompactObjectOutputStream.TYPE_THIN_DESCRIPTOR: String className = readUTF(); - Class clazz = loadClass(className); + Class clazz = classResolver.resolve(className); return ObjectStreamClass.lookupAny(clazz); default: throw new StreamCorruptedException( @@ -82,7 +71,7 @@ class CompactObjectInputStream extends ObjectInputStream { protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { Class clazz; try { - clazz = loadClass(desc.getName()); + clazz = classResolver.resolve(desc.getName()); } catch (ClassNotFoundException ex) { clazz = super.resolveClass(desc); } @@ -90,28 +79,4 @@ class CompactObjectInputStream extends ObjectInputStream { return clazz; } - protected Class loadClass(String className) throws ClassNotFoundException { - // Query the cache first. - Class clazz; - clazz = classCache.get(className); - if (clazz != null) { - return clazz; - } - - // And then try to load. - clazz = classLoader.loadClass(className); - - classCache.put(className, clazz); - return clazz; - } - - private static ClassLoader defaultClassLoader() { - final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); - if (contextClassLoader != null) { - return contextClassLoader; - } - - return CompactObjectInputStream.class.getClassLoader(); - } - } diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java index 3bf80a82ca..4efab6c9c8 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java @@ -43,7 +43,7 @@ import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; */ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { - private final ClassLoader classLoader; + private final ClassResolver classResolver; /** * Creates a new decoder whose maximum object size is {@code 1048576} @@ -64,7 +64,7 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { * will be raised. */ public ObjectDecoder(int maxObjectSize) { - this(maxObjectSize, null); + this(maxObjectSize, ClassResolvers.cachingResolver(null)); } /** @@ -74,12 +74,12 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { * if the length of the received object is greater * than this value, {@link StreamCorruptedException} * will be raised. - * @param classLoader the {@link ClassLoader} which will load the class + * @param classResolver the {@link ClassResolver} which will load the class * of the serialized object */ - public ObjectDecoder(int maxObjectSize, ClassLoader classLoader) { + public ObjectDecoder(int maxObjectSize, ClassResolver classResolver) { super(maxObjectSize, 0, 4, 0, 4); - this.classLoader = classLoader; + this.classResolver = classResolver; } @Override @@ -92,7 +92,7 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { } return new CompactObjectInputStream( - new ChannelBufferInputStream(frame), classLoader).readObject(); + new ChannelBufferInputStream(frame), classResolver).readObject(); } @Override diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java index aa4aa439c0..158f0ad3a1 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java @@ -119,7 +119,7 @@ public class ObjectDecoderInputStream extends InputStream implements "data length too big: " + dataLen + " (max: " + maxObjectSize + ')'); } - return new CompactObjectInputStream(in, classLoader).readObject(); + return new CompactObjectInputStream(in, ClassResolvers.cachingResolver(classLoader)).readObject(); } @Override From 99e9da1e75188bf78f71d5b89e627c8372212cde Mon Sep 17 00:00:00 2001 From: alepar Date: Tue, 22 Nov 2011 18:09:37 +0400 Subject: [PATCH 5/9] sharing classResolver cache across all CompactObjectInputStream's in the same way, as we did in ObjectDecoder --- .../codec/serialization/ObjectDecoderInputStream.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java index 158f0ad3a1..a1590fee8c 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java @@ -35,8 +35,8 @@ public class ObjectDecoderInputStream extends InputStream implements ObjectInput { private final DataInputStream in; - private final ClassLoader classLoader; private final int maxObjectSize; + private final ClassResolver classResolver; /** * Creates a new {@link ObjectInput}. @@ -104,7 +104,7 @@ public class ObjectDecoderInputStream extends InputStream implements } else { this.in = new DataInputStream(in); } - this.classLoader = classLoader; + this.classResolver = ClassResolvers.cachingResolver(classLoader); this.maxObjectSize = maxObjectSize; } @@ -119,7 +119,7 @@ public class ObjectDecoderInputStream extends InputStream implements "data length too big: " + dataLen + " (max: " + maxObjectSize + ')'); } - return new CompactObjectInputStream(in, ClassResolvers.cachingResolver(classLoader)).readObject(); + return new CompactObjectInputStream(in, classResolver).readObject(); } @Override From 7e6d07afaf057df683a48901f23aff55a117588e Mon Sep 17 00:00:00 2001 From: alepar Date: Tue, 22 Nov 2011 18:16:30 +0400 Subject: [PATCH 6/9] use weak cache as default cache - it doesn't break class unloading providing multiple implementations for caching, each good for its own specific use-case --- .../codec/serialization/ClassResolver.java | 4 + .../codec/serialization/ClassResolvers.java | 58 +++++++++++-- .../codec/serialization/ObjectDecoder.java | 2 +- .../ObjectDecoderInputStream.java | 2 +- .../codec/serialization/ReferenceMap.java | 87 +++++++++++++++++++ .../codec/serialization/SoftReferenceMap.java | 18 ++++ .../codec/serialization/WeakReferenceMap.java | 18 ++++ 7 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/ReferenceMap.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/SoftReferenceMap.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/serialization/WeakReferenceMap.java diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java index a6fa1c52d7..6f9f13b887 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java @@ -1,5 +1,9 @@ package org.jboss.netty.handler.codec.serialization; + +/** + * please use {@link ClassResolvers} as instance factory + */ interface ClassResolver { Class resolve(String className) throws ClassNotFoundException; diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java index e802838080..4df8e3d3bc 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java @@ -1,24 +1,66 @@ package org.jboss.netty.handler.codec.serialization; +import java.lang.ref.Reference; import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; public class ClassResolvers { - - public static ClassResolver cachingResolver(ClassLoader classLoader) { - if (classLoader == null) { - classLoader = defaultClassLoader(); - } - return new CachingClassResolver(new ClassloaderClassResolver(classLoader), new HashMap>()); + /** + * non-agressive non-concurrent cache + * good for non-shared default cache + * + * @param classLoader - specific classLoader to use, or null if you want to revert to default + * @return new instance of class resolver + */ + public static ClassResolver weakCachingResolver(ClassLoader classLoader) { + return new CachingClassResolver(new ClassloaderClassResolver(defaultClassLoader(classLoader)), new WeakReferenceMap>(new HashMap>>())); } - static ClassLoader defaultClassLoader() { + /** + * agressive non-concurrent cache + * good for non-shared cache, when we're not worried about class unloading + * + * @param classLoader - specific classLoader to use, or null if you want to revert to default + * @return new instance of class resolver + */ + public static ClassResolver softCachingResolver(ClassLoader classLoader) { + return new CachingClassResolver(new ClassloaderClassResolver(defaultClassLoader(classLoader)), new SoftReferenceMap>(new HashMap>>())); + } + + /** + * non-agressive concurrent cache + * good for shared cache, when we're worried about class unloading + * + * @param classLoader - specific classLoader to use, or null if you want to revert to default + * @return new instance of class resolver + */ + public static ClassResolver weakCachingConcurrentResolver(ClassLoader classLoader) { + return new CachingClassResolver(new ClassloaderClassResolver(defaultClassLoader(classLoader)), new WeakReferenceMap>(new ConcurrentHashMap>>())); + } + + /** + * agressive concurrent cache + * good for shared cache, when we're not worried about class unloading + * + * @param classLoader - specific classLoader to use, or null if you want to revert to default + * @return new instance of class resolver + */ + public static ClassResolver softCachingConcurrentResolver(ClassLoader classLoader) { + return new CachingClassResolver(new ClassloaderClassResolver(defaultClassLoader(classLoader)), new SoftReferenceMap>(new ConcurrentHashMap>>())); + } + + static ClassLoader defaultClassLoader(ClassLoader classLoader) { + if (classLoader != null) { + return classLoader; + } + final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { return contextClassLoader; } - return CompactObjectInputStream.class.getClassLoader(); + return ClassResolvers.class.getClassLoader(); } } diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java index 4efab6c9c8..73fd1eb2c0 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java @@ -64,7 +64,7 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { * will be raised. */ public ObjectDecoder(int maxObjectSize) { - this(maxObjectSize, ClassResolvers.cachingResolver(null)); + this(maxObjectSize, ClassResolvers.weakCachingResolver(null)); } /** diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java index a1590fee8c..234035bd74 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoderInputStream.java @@ -104,7 +104,7 @@ public class ObjectDecoderInputStream extends InputStream implements } else { this.in = new DataInputStream(in); } - this.classResolver = ClassResolvers.cachingResolver(classLoader); + this.classResolver = ClassResolvers.weakCachingResolver(classLoader); this.maxObjectSize = maxObjectSize; } diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ReferenceMap.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ReferenceMap.java new file mode 100644 index 0000000000..64a3e3c750 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ReferenceMap.java @@ -0,0 +1,87 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.lang.ref.Reference; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +abstract class ReferenceMap implements Map { + + private final Map> delegate; + + protected ReferenceMap(Map> delegate) { + this.delegate = delegate; + } + + abstract Reference fold(V value); + + private V unfold(Reference ref) { + if (ref == null) { + return null; + } + + return ref.get(); + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return delegate.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public V get(Object key) { + return unfold(delegate.get(key)); + } + + @Override + public V put(K key, V value) { + return unfold(delegate.put(key, fold(value))); + } + + @Override + public V remove(Object key) { + return unfold(delegate.remove(key)); + } + + @Override + public void putAll(Map m) { + for (Entry entry : m.entrySet()) { + delegate.put(entry.getKey(), fold(entry.getValue())); + } + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public Set keySet() { + return delegate.keySet(); + } + + @Override + public Collection values() { + throw new UnsupportedOperationException(); + } + + @Override + public Set> entrySet() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/SoftReferenceMap.java b/src/main/java/org/jboss/netty/handler/codec/serialization/SoftReferenceMap.java new file mode 100644 index 0000000000..7bf82e02da --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/SoftReferenceMap.java @@ -0,0 +1,18 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.util.Map; + +public class SoftReferenceMap extends ReferenceMap { + + public SoftReferenceMap(Map> delegate) { + super(delegate); + } + + @Override + Reference fold(V value) { + return new SoftReference(value); + } + +} diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/WeakReferenceMap.java b/src/main/java/org/jboss/netty/handler/codec/serialization/WeakReferenceMap.java new file mode 100644 index 0000000000..9217baac0c --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/WeakReferenceMap.java @@ -0,0 +1,18 @@ +package org.jboss.netty.handler.codec.serialization; + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.Map; + +public class WeakReferenceMap extends ReferenceMap { + + public WeakReferenceMap(Map> delegate) { + super(delegate); + } + + @Override + Reference fold(V value) { + return new WeakReference(value); + } + +} From cdbaeb86b07580858f6006207c5313dc573591fe Mon Sep 17 00:00:00 2001 From: alepar Date: Wed, 23 Nov 2011 02:57:32 +0400 Subject: [PATCH 7/9] adding class resolver with disabled cache, fixing unit tests --- .../handler/codec/serialization/ClassResolvers.java | 10 +++++++++- .../serialization/CompactObjectSerializationTest.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java index 4df8e3d3bc..cbc4d1db15 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolvers.java @@ -6,6 +6,15 @@ import java.util.concurrent.ConcurrentHashMap; public class ClassResolvers { + /** + * cache disabled + * @param classLoader - specific classLoader to use, or null if you want to revert to default + * @return new instance of class resolver + */ + public static ClassResolver cacheDisabled(ClassLoader classLoader) { + return new ClassloaderClassResolver(defaultClassLoader(classLoader)); + } + /** * non-agressive non-concurrent cache * good for non-shared default cache @@ -62,5 +71,4 @@ public class ClassResolvers { return ClassResolvers.class.getClassLoader(); } - } diff --git a/src/test/java/org/jboss/netty/handler/codec/serialization/CompactObjectSerializationTest.java b/src/test/java/org/jboss/netty/handler/codec/serialization/CompactObjectSerializationTest.java index 0db5000c7c..b233981ddb 100644 --- a/src/test/java/org/jboss/netty/handler/codec/serialization/CompactObjectSerializationTest.java +++ b/src/test/java/org/jboss/netty/handler/codec/serialization/CompactObjectSerializationTest.java @@ -32,7 +32,7 @@ public class CompactObjectSerializationTest { PipedOutputStream pipeOut = new PipedOutputStream(); PipedInputStream pipeIn = new PipedInputStream(pipeOut); CompactObjectOutputStream out = new CompactObjectOutputStream(pipeOut); - CompactObjectInputStream in = new CompactObjectInputStream(pipeIn); + CompactObjectInputStream in = new CompactObjectInputStream(pipeIn, ClassResolvers.cacheDisabled(null)); out.writeObject(List.class); Assert.assertSame(List.class, in.readObject()); } From 800a9fc20d7258275f687b29ef8eddea3f944192 Mon Sep 17 00:00:00 2001 From: alepar Date: Wed, 23 Nov 2011 14:48:42 +0400 Subject: [PATCH 8/9] making interface public, so that others can implement it jic --- .../jboss/netty/handler/codec/serialization/ClassResolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java index 6f9f13b887..73958e1108 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassResolver.java @@ -4,7 +4,7 @@ package org.jboss.netty.handler.codec.serialization; /** * please use {@link ClassResolvers} as instance factory */ -interface ClassResolver { +public interface ClassResolver { Class resolve(String className) throws ClassNotFoundException; From cee5ee5679de2a8900afe9bbf05f973ace08ce71 Mon Sep 17 00:00:00 2001 From: alepar Date: Wed, 23 Nov 2011 15:18:43 +0400 Subject: [PATCH 9/9] now able to resolve array types to classes --- .../codec/serialization/ClassloaderClassResolver.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java index 545e8e3f08..691b9dd0c9 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ClassloaderClassResolver.java @@ -10,7 +10,11 @@ class ClassloaderClassResolver implements ClassResolver { @Override public Class resolve(String className) throws ClassNotFoundException { - return classLoader.loadClass(className); + try { + return classLoader.loadClass(className); + } catch (ClassNotFoundException e) { + return Class.forName(className, false, classLoader); + } } }