Skip to content

Commit 04283ce

Browse files
committed
Several optimizations; bug fix for swing
1 parent f867b79 commit 04283ce

23 files changed

Lines changed: 787 additions & 327 deletions

Code/ChroniclerJ/nondeterministic-methods.txt

Lines changed: 1 addition & 53 deletions
Large diffs are not rendered by default.

Code/ChroniclerJ/src/com/rits/cloning/Cloner.java

Lines changed: 152 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import java.net.URI;
1010
import java.net.URL;
1111
import java.util.ArrayList;
12+
import java.util.Collection;
13+
import java.util.Collections;
1214
import java.util.GregorianCalendar;
1315
import java.util.HashMap;
1416
import java.util.HashSet;
@@ -23,8 +25,7 @@
2325
import java.util.concurrent.ConcurrentHashMap;
2426
import java.util.regex.Pattern;
2527

26-
import org.objenesis.Objenesis;
27-
import org.objenesis.ObjenesisStd;
28+
import javax.activation.FileDataSource;
2829

2930
/**
3031
* Cloner: deep clone objects.
@@ -37,8 +38,9 @@
3738
*/
3839
public class Cloner
3940
{
40-
private final Objenesis objenesis;
41+
private final IInstantiationStrategy instantiationStrategy;
4142
private final Set<Class<?>> ignored = new HashSet<Class<?>>();
43+
private final Set<Class<?>> ignoredInstanceOf = new HashSet<Class<?>>();
4244
private final Set<Class<?>> nullInstead = new HashSet<Class<?>>();
4345
private final Map<Class<?>, IFastCloner> fastCloners = new HashMap<Class<?>, IFastCloner>();
4446
private final Map<Object, Boolean> ignoredInstances = new IdentityHashMap<Object, Boolean>();
@@ -50,13 +52,13 @@ public class Cloner
5052

5153
public Cloner()
5254
{
53-
objenesis = new ObjenesisStd();
55+
this.instantiationStrategy = ObjenesisInstantiationStrategy.getInstance();
5456
init();
5557
}
5658

57-
public Cloner(final Objenesis objenesis)
59+
public Cloner(final IInstantiationStrategy instantiationStrategy)
5860
{
59-
this.objenesis = objenesis;
61+
this.instantiationStrategy = instantiationStrategy;
6062
init();
6163
}
6264

@@ -190,7 +192,6 @@ public void registerStaticFields(final Class<?>... classes)
190192
final int mods = field.getModifiers();
191193
if (Modifier.isStatic(mods) && !field.getType().isPrimitive())
192194
{
193-
// System.out.println(c + " . " + field.getName());
194195
registerConstant(c, field.getName());
195196
}
196197
}
@@ -220,6 +221,27 @@ public void dontClone(final Class<?>... c)
220221
ignored.add(cl);
221222
}
222223
}
224+
public boolean isIgnored(Class<?> clz)
225+
{
226+
for(final Class<?> c : ignored)
227+
{
228+
if (c.isAssignableFrom(clz))
229+
return true;
230+
}
231+
return false;
232+
}
233+
public void dontCloneInstanceOf(final Class<?>... c)
234+
{
235+
for (final Class<?> cl : c)
236+
{
237+
ignoredInstanceOf.add(cl);
238+
}
239+
}
240+
241+
public void setDontCloneInstanceOf(final Class<?>... c)
242+
{
243+
dontCloneInstanceOf(c);
244+
}
223245

224246
/**
225247
* instead of cloning these classes will set the field to null
@@ -276,10 +298,9 @@ public void registerFastCloner(final Class<?> c, final IFastCloner fastCloner)
276298
* @param c the class
277299
* @return a new instance of c
278300
*/
279-
@SuppressWarnings("unchecked")
280-
public <T> T newInstance(final Class<T> c)
301+
protected <T> T newInstance(final Class<T> c)
281302
{
282-
return (T) objenesis.newInstance(c);
303+
return instantiationStrategy.newInstance(c);
283304
}
284305

285306
@SuppressWarnings("unchecked")
@@ -366,46 +387,85 @@ public <T> T shallowClone(final T o)
366387
}
367388

368389
// caches immutables for quick reference
369-
private final ConcurrentHashMap<Class<?>, Boolean> immutables = new ConcurrentHashMap<Class<?>, Boolean>();
370-
private boolean isIgnored(final Class<?> clz)
390+
private final ConcurrentHashMap<Class<?>, Boolean> immutables = new ConcurrentHashMap<Class<?>, Boolean>();
391+
private boolean cloneAnonymousParent = true;
392+
393+
/**
394+
* override this to decide if a class is immutable. Immutable classes are not cloned.
395+
*
396+
* @param clz the class under check
397+
* @return true to mark clz as immutable and skip cloning it
398+
*/
399+
protected boolean considerImmutable(final Class<?> clz)
371400
{
372-
for(Class<?> c : ignored)
373-
{
374-
if(c.isAssignableFrom(clz))
375-
return true;
376-
}
377401
return false;
378402
}
403+
404+
protected Class<?> getImmutableAnnotation()
405+
{
406+
return Immutable.class;
407+
}
408+
409+
/**
410+
* decides if a class is to be considered immutable or not
411+
*
412+
* @param clz the class under check
413+
* @return true if the clz is considered immutable
414+
*/
379415
private boolean isImmutable(final Class<?> clz)
380416
{
381-
final Boolean b = immutables.get(clz);
382-
if (b != null && b) return true;
383-
for (final Annotation annotation : clz.getDeclaredAnnotations())
384-
{
385-
if (annotation.annotationType() == Immutable.class)
386-
{
387-
immutables.put(clz, Boolean.TRUE);
388-
return true;
389-
}
390-
}
391-
Class<?> c = clz.getSuperclass();
392-
while (c != null && c != Object.class)
393-
{
394-
for (final Annotation annotation : c.getDeclaredAnnotations())
395-
{
396-
if (annotation.annotationType() == Immutable.class)
397-
{
398-
final Immutable im = (Immutable) annotation;
399-
if (im.subClass())
400-
{
401-
immutables.put(clz, Boolean.TRUE);
402-
return true;
403-
}
404-
}
405-
}
406-
c = c.getSuperclass();
417+
if(
418+
clz.getName().equals("java.util.HashSet")
419+
//clz.getName().startsWith("java.util")
420+
//&& !clz.getName().equals("java.util.HashMap")
421+
//&& !clz.getName().equals("java.util.LinkedHashMap")
422+
//&& !clz.getName().startsWith("java.util.Hashtable")
423+
//&& !clz.getName().equals("java.util.ArrayList")
424+
//&& !clz.getName().contains("Map")
425+
//&& ! clz.getName().startsWith("java.util.Collections")
426+
////&& !clz.getName().equals("java.util.HashSet") //bad
427+
//&& !clz.getName().startsWith("java.util.Linked")
428+
//&& !clz.getName().contains("Vector")
429+
//&& !clz.getName().equals("java.util.concurrent.CopyOnWriteArrayList")
430+
//&& !clz.getName().equals("java.util.Arrays$ArrayList")
431+
)
432+
{
433+
// System.out.println(clz.getName());
434+
return true;
407435
}
436+
final Boolean isIm = immutables.get(clz);
437+
if (isIm != null) return isIm;
438+
if (considerImmutable(clz)) return true;
408439
return false;
440+
441+
// final Class<?> immutableAnnotation = getImmutableAnnotation();
442+
// for (final Annotation annotation : clz.getDeclaredAnnotations())
443+
// {
444+
// if (annotation.annotationType() == immutableAnnotation)
445+
// {
446+
// immutables.put(clz, Boolean.TRUE);
447+
// return true;
448+
// }
449+
// }
450+
// Class<?> c = clz.getSuperclass();
451+
// while (c != null && c != Object.class)
452+
// {
453+
// for (final Annotation annotation : c.getDeclaredAnnotations())
454+
// {
455+
// if (annotation.annotationType() == Immutable.class)
456+
// {
457+
// final Immutable im = (Immutable) annotation;
458+
// if (im.subClass())
459+
// {
460+
// immutables.put(clz, Boolean.TRUE);
461+
// return true;
462+
// }
463+
// }
464+
// }
465+
// c = c.getSuperclass();
466+
// }
467+
// immutables.put(clz, Boolean.FALSE);
468+
// return false;
409469
}
410470

411471
/**
@@ -422,9 +482,12 @@ public <T> T cloneInternal(final T o, final Map<Object, Object> clones) throws I
422482
if (clz.isEnum()) return o;
423483
// skip cloning ignored classes
424484
if (nullInstead.contains(clz)) return null;
425-
if (ignored.contains(clz)) return o;
426-
if (isImmutable(clz)) return o;
427485
if (isIgnored(clz)) return o;
486+
for (final Class<?> iClz : ignoredInstanceOf)
487+
{
488+
if (iClz.isAssignableFrom(clz)) return o;
489+
}
490+
if (isImmutable(clz)) return o;
428491
if (o instanceof IFreezable)
429492
{
430493
final IFreezable f = (IFreezable) o;
@@ -451,13 +514,21 @@ public <T> T cloneInternal(final T o, final Map<Object, Object> clones) throws I
451514
{
452515
final int length = Array.getLength(o);
453516
final T newInstance = (T) Array.newInstance(clz.getComponentType(), length);
454-
if(clones != null)
517+
if (clones != null)
518+
{
455519
clones.put(o, newInstance);
520+
}
456521
for (int i = 0; i < length; i++)
457522
{
458523
final Object v = Array.get(o, i);
459524
final Object clone = clones != null ? cloneInternal(v, clones) : v;
525+
try{
460526
Array.set(newInstance, i, clone);
527+
}
528+
catch(Exception ex)
529+
{
530+
Array.set(newInstance, i, v);
531+
}
461532
}
462533
return newInstance;
463534
}
@@ -484,9 +555,17 @@ public <T> T cloneInternal(final T o, final Map<Object, Object> clones) throws I
484555
} else
485556
{
486557
final Object fieldObject = field.get(o);
487-
final boolean shouldClone = cloneSynthetics || (!cloneSynthetics && !field.isSynthetic());
558+
final boolean shouldClone = (cloneSynthetics || (!cloneSynthetics && !field.isSynthetic())) && (cloneAnonymousParent || ((!cloneAnonymousParent && !isAnonymousParent(field))));
488559
final Object fieldObjectClone = clones != null ? (shouldClone ? cloneInternal(fieldObject, clones) : fieldObject) : fieldObject;
489-
field.set(newInstance, fieldObjectClone);
560+
try
561+
{
562+
field.set(newInstance, fieldObjectClone);
563+
}
564+
catch(Exception ex)
565+
{
566+
// ex.printStackTrace();
567+
// System.exit(-1);
568+
}
490569
if (dumpClonedClasses && fieldObjectClone != fieldObject)
491570
{
492571
System.out.println("cloned field>" + field + " -- of class " + o.getClass());
@@ -497,6 +576,11 @@ public <T> T cloneInternal(final T o, final Map<Object, Object> clones) throws I
497576
return newInstance;
498577
}
499578

579+
private boolean isAnonymousParent(final Field field)
580+
{
581+
return "this$0".equals(field.getName());
582+
}
583+
500584
/**
501585
* copies all properties from src to dest. Src and dest can be of different class, provided they contain same field names/types
502586
*
@@ -552,16 +636,18 @@ private void addAll(final List<Field> l, final Field[] fields)
552636
{
553637
for (final Field field : fields)
554638
{
555-
if (!field.isAccessible()) field.setAccessible(true);
556-
if(!Modifier.isStatic(field.getModifiers()))
557-
l.add(field);
639+
if (!field.isAccessible())
640+
{
641+
field.setAccessible(true);
642+
}
643+
l.add(field);
558644
}
559645
}
560646

561647
/**
562-
* reflection utils
648+
* reflection utils, override this to choose which fields to clone
563649
*/
564-
private List<Field> allFields(final Class<?> c)
650+
protected List<Field> allFields(final Class<?> c)
565651
{
566652
List<Field> l = fieldsCache.get(c);
567653
if (l == null)
@@ -603,4 +689,17 @@ public void setCloningEnabled(final boolean cloningEnabled)
603689
{
604690
this.cloningEnabled = cloningEnabled;
605691
}
692+
693+
/**
694+
* if false, anonymous classes parent class won't be cloned. Default is true
695+
*/
696+
public void setCloneAnonymousParent(final boolean cloneAnonymousParent)
697+
{
698+
this.cloneAnonymousParent = cloneAnonymousParent;
699+
}
700+
701+
public boolean isCloneAnonymousParent()
702+
{
703+
return cloneAnonymousParent;
704+
}
606705
}

Code/ChroniclerJ/src/com/rits/cloning/FastClonerArrayList.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,15 @@ public class FastClonerArrayList implements IFastCloner
1212
{
1313
@SuppressWarnings({ "unchecked", "rawtypes" })
1414
public Object clone(final Object t, final Cloner cloner, final Map<Object, Object> clones) throws IllegalAccessException
15-
{
16-
final ArrayList al = (ArrayList) t;
17-
// synchronized (t) {
18-
19-
20-
21-
final ArrayList l = new ArrayList();
22-
for (final Object o : al)
23-
{
24-
final Object cloneInternal = cloner.cloneInternal(o, clones);
25-
l.add(cloneInternal);
26-
}
27-
return l;
28-
29-
// }
15+
{
16+
final ArrayList al = (ArrayList) t;
17+
final ArrayList l = new ArrayList();
18+
for (final Object o : al)
19+
{
20+
final Object cloneInternal = cloner.cloneInternal(o, clones);
21+
l.add(cloneInternal);
22+
}
23+
return l;
3024
}
3125

3226
}

Code/ChroniclerJ/src/com/rits/cloning/FastClonerConcurrentHashMap.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,15 @@ public class FastClonerConcurrentHashMap implements IFastCloner
1313
@SuppressWarnings({ "unchecked", "rawtypes" })
1414
public Object clone(final Object t, final Cloner cloner, final Map<Object, Object> clones) throws IllegalAccessException
1515
{
16-
synchronized (t) {
17-
1816
final ConcurrentHashMap<Object, Object> m = (ConcurrentHashMap) t;
1917
final ConcurrentHashMap result = new ConcurrentHashMap();
20-
synchronized (m.entrySet()) {
21-
2218
for (final Map.Entry e : m.entrySet())
2319
{
24-
synchronized (e.getKey()) {
25-
26-
2720
final Object key = cloner.cloneInternal(e.getKey(), clones);
2821
final Object value = cloner.cloneInternal(e.getValue(), clones);
29-
if(key != null && value != null)
30-
result.put(key, value);
31-
}
22+
if (key != null && value != null)
23+
result.put(key, value);
3224
}
33-
3425
return result;
35-
}
36-
}
3726
}
3827
}

0 commit comments

Comments
 (0)