Fixed conflicts

Nikhil Sarda [2012-08-09 20:48:34]
Fixed conflicts

Merge branch 'master' of ssh://ase.cs.columbia.edu/in-vivo

Conflicts:
	testcase-generation-tester/.classpath
	testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceExportRunner.java
Filename
testcase-generation-tester/src/edu/columbia/cs/psl/invivo/example/ReaderUser.java
testcase-generation/src/edu/columbia/cs/psl/invivo/bench/WallaceLogExplorer.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/Constants.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedLog.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedSerializableLog.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/Log.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/MethodCall.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/SerializableLog.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceExportRunner.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceUncaughtExceptionHandler.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/CloningAdviceAdapter.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldClassVisitor.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldMethodVisitor.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingClassVisitor.java
testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingMethodVisitor.java
testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayClassVisitor.java
testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayMethodVisitor.java
testcase-generation/src/edu/columbia/cs/psl/invivo/replay/ReplayRunner.java
diff --git a/testcase-generation-tester/src/edu/columbia/cs/psl/invivo/example/ReaderUser.java b/testcase-generation-tester/src/edu/columbia/cs/psl/invivo/example/ReaderUser.java
index 9bb3498..5e4ffdb 100644
--- a/testcase-generation-tester/src/edu/columbia/cs/psl/invivo/example/ReaderUser.java
+++ b/testcase-generation-tester/src/edu/columbia/cs/psl/invivo/example/ReaderUser.java
@@ -15,6 +15,7 @@ import java.lang.reflect.Modifier;
 import java.util.Arrays;

 import edu.columbia.cs.psl.invivo.record.ExportedLog;
+import edu.columbia.cs.psl.invivo.record.Log;

 public class ReaderUser extends InputStreamReader {
 	protected ReaderUser(InputStream in) {
@@ -37,7 +38,7 @@ public class ReaderUser extends InputStreamReader {
 			f.exists();
 			f.getAbsoluteFile();
 			BufferedReader r = new BufferedReader(new FileReader("in-vivo.log"));
-			char[] buf = new char[2];
+			char[] buf = new char[5000];
 //			int zz = read(new byte[4]);
 //			System.out.println("zz: " + zz);
 			int charsRead = 0;
@@ -48,8 +49,9 @@ public class ReaderUser extends InputStreamReader {
 			{
 				charsRead = r.read(buf, 0, buf.length);
 				System.out.println(charsRead);
-				System.out.println(buf);
-				Thread.sleep(100);
+//				System.out.println(buf);
+//				Thread.sleep(100);
+//				System.out.println("Size" + Log.logsize);
 			}
 			c++;
 			System.out.println(c);
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/bench/WallaceLogExplorer.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/bench/WallaceLogExplorer.java
new file mode 100644
index 0000000..ef6315f
--- /dev/null
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/bench/WallaceLogExplorer.java
@@ -0,0 +1,23 @@
+package edu.columbia.cs.psl.invivo.bench;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.ObjectInputStream;
+
+import edu.columbia.cs.psl.invivo.record.ExportedSerializableLog;
+
+public class WallaceLogExplorer {
+	public static void main(String[] args) throws Exception {
+		File f = new File("instrumented/wallace_serializable_1344527362195.log");
+		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
+		ExportedSerializableLog log = (ExportedSerializableLog) ois.readObject();
+		Object[] alog = ExportedSerializableLog.aLog;
+
+		char[] clog = ExportedSerializableLog.cLog;
+		byte[] blog = ExportedSerializableLog.bLog;
+		String[] ownersA = ExportedSerializableLog.aLog_owners;
+		System.out.println(ExportedSerializableLog.aLog_fill);
+		System.out.println(ExportedSerializableLog.cLog_fill);
+		System.out.println(ExportedSerializableLog.dLog_fill);
+	}
+}
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Constants.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Constants.java
index ef4be46..9eb486a 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Constants.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Constants.java
@@ -5,12 +5,14 @@ public interface Constants {
 	public static String PREV_VALUE_PREFIX = "__origValue_";
 //	public static String LOGGED_CALL_PREFIX = "__loggedValueAt_";

-	public static String LOG_DUMP_CLASS = "edu/columbia/cs/psl/invivo/record/Log";
-	public static String LOG_REPLAY_CLASS = "edu/columbia/cs/psl/invivo/record/ExportedLog";
+//	public static String LOG_DUMP_CLASS = "edu/columbia/cs/psl/invivo/record/Log";
+//	public static String LOG_REPLAY_CLASS = "edu/columbia/cs/psl/invivo/record/ExportedLog";

-	public static int DEFAULT_LOG_SIZE = 1000;
-	public static int MAX_LOG_SIZE = 500000;
-	public static double LOG_GROWTH_RATE = 1.5;
+	public static int DEFAULT_LOG_SIZE = 2000;
+	public static int MAX_LOG_SIZE = 40000000;
+	public static int VERY_MAX_LOG_SIZE = 400000000;
+
+	public static double LOG_GROWTH_RATE = 2.5;
 	public static String REPLAY_CLASS_SUFFIX = "InvivoReplay";
 	public static String INNER_COPY_METHOD_NAME = "_Invivo___copy";
 	public static String OUTER_COPY_METHOD_NAME = "_Invivo_copy";
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedLog.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedLog.java
index c803c69..c16e511 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedLog.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedLog.java
@@ -1,38 +1,16 @@
 package edu.columbia.cs.psl.invivo.record;

+import java.util.HashMap;
+
 public class ExportedLog {
 	public static Object[] aLog = new Object[Constants.DEFAULT_LOG_SIZE];
-	public static int[] iLog = new int[Constants.DEFAULT_LOG_SIZE];
-	public static long[] jLog = new long[Constants.DEFAULT_LOG_SIZE];
-	public static float[] fLog = new float[Constants.DEFAULT_LOG_SIZE];
-	public static double[] dLog = new double[Constants.DEFAULT_LOG_SIZE];
-	public static byte[] bLog = new byte[Constants.DEFAULT_LOG_SIZE];
-	public static boolean[] zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
-	public static char[] cLog = new char[Constants.DEFAULT_LOG_SIZE];
-	public static short[] sLog = new short[Constants.DEFAULT_LOG_SIZE];
-	public static Object lock = new Object();
-	public static int aLog_fill, iLog_fill, jLog_fill, fLog_fill, dLog_fill, bLog_fill, zLog_fill, cLog_fill, sLog_fill;
-	public static int aLog_replayIndex , iLog_replayIndex, jLog_replayIndex, fLog_replayIndex, dLog_replayIndex, bLog_replayIndex, zLog_replayIndex, cLog_replayIndex, sLog_replayIndex;
+	public static String[] aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];

+	public static int aLog_fill;
+	public static HashMap<String, Integer> aLog_replayIndex = new HashMap<String, Integer>();
 	public static void clearLog() {
 		aLog = new Object[Constants.DEFAULT_LOG_SIZE];
-		iLog = new int[Constants.DEFAULT_LOG_SIZE];
-		jLog = new long[Constants.DEFAULT_LOG_SIZE];
-		fLog = new float[Constants.DEFAULT_LOG_SIZE];
-		dLog = new double[Constants.DEFAULT_LOG_SIZE];
-		bLog = new byte[Constants.DEFAULT_LOG_SIZE];
-		zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
-		cLog = new char[Constants.DEFAULT_LOG_SIZE];
-		sLog = new short[Constants.DEFAULT_LOG_SIZE];
-
+		aLog_owners =  new String[Constants.DEFAULT_LOG_SIZE];
 		aLog_fill = 0;
-		iLog_fill = 0;
-		jLog_fill = 0;
-		fLog_fill = 0;
-		dLog_fill = 0;
-		bLog_fill = 0;
-		zLog_fill = 0;
-		cLog_fill = 0;
-		sLog_fill = 0;
 	}
 }
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedSerializableLog.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedSerializableLog.java
new file mode 100644
index 0000000..468aedb
--- /dev/null
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/ExportedSerializableLog.java
@@ -0,0 +1,125 @@
+package edu.columbia.cs.psl.invivo.record;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+
+public class ExportedSerializableLog implements Serializable {
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 1166783255069514273L;
+	public static Object[]	aLog	= new Object[Constants.DEFAULT_LOG_SIZE];
+	public static int[] iLog = new int[Constants.DEFAULT_LOG_SIZE];
+	public static long[] jLog = new long[Constants.DEFAULT_LOG_SIZE];
+	public static float[] fLog = new float[Constants.DEFAULT_LOG_SIZE];
+	public static double[] dLog = new double[Constants.DEFAULT_LOG_SIZE];
+	public static byte[] bLog = new byte[Constants.DEFAULT_LOG_SIZE];
+	public static boolean[] zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
+	public static char[] cLog = new char[Constants.DEFAULT_LOG_SIZE];
+	public static short[] sLog = new short[Constants.DEFAULT_LOG_SIZE];
+	public static Object lock = new Object();
+	public static int aLog_fill, iLog_fill, jLog_fill, fLog_fill, dLog_fill, bLog_fill, zLog_fill, cLog_fill, sLog_fill;
+
+	public static HashMap<String,Integer> aLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> iLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> jLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> fLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> dLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> bLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> zLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> cLog_replayIndex = new HashMap<String,Integer>();
+	public static HashMap<String,Integer> sLog_replayIndex = new HashMap<String,Integer>();
+
+	public static String[] aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] iLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] jLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] fLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] dLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] bLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] zLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] cLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] sLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+
+	public static void clearLog() {
+		aLog = new Serializable[Constants.DEFAULT_LOG_SIZE];
+		aLog_fill = 0;
+	}
+
+	private void writeObject(ObjectOutputStream oos) throws IOException {
+		oos.defaultWriteObject();
+		oos.writeInt(aLog_fill);
+		oos.writeObject(aLog);
+		oos.writeInt(iLog_fill);
+		oos.writeObject(iLog);
+		oos.writeInt(jLog_fill);
+		oos.writeObject(jLog);
+		oos.writeInt(fLog_fill);
+		oos.writeObject(fLog);
+		oos.writeInt(dLog_fill);
+		oos.writeObject(dLog);
+		oos.writeInt(bLog_fill);
+		oos.writeObject(bLog);
+		oos.writeInt(zLog_fill);
+		oos.writeObject(zLog);
+		oos.writeInt(cLog_fill);
+		oos.writeObject(cLog);
+		oos.writeInt(sLog_fill);
+		oos.writeObject(sLog);
+
+		oos.writeObject(aLog_owners);
+		oos.writeObject(iLog_owners);
+		oos.writeObject(jLog_owners);
+		oos.writeObject(fLog_owners);
+		oos.writeObject(dLog_owners);
+		oos.writeObject(bLog_owners);
+		oos.writeObject(zLog_owners);
+		oos.writeObject(cLog_owners);
+		oos.writeObject(sLog_owners);
+
+	}
+
+	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+		ois.defaultReadObject();
+		aLog_fill = ois.readInt();
+		aLog = (Object[]) ois.readObject();
+		iLog_fill = ois.readInt();
+		iLog = (int[]) ois.readObject();
+		jLog_fill = ois.readInt();
+		jLog = (long[]) ois.readObject();
+		fLog_fill = ois.readInt();
+		fLog = (float[]) ois.readObject();
+		dLog_fill = ois.readInt();
+		dLog = (double[]) ois.readObject();
+		bLog_fill = ois.readInt();
+		bLog = (byte[]) ois.readObject();
+		zLog_fill = ois.readInt();
+		zLog = (boolean[]) ois.readObject();
+		cLog_fill = ois.readInt();
+		cLog = (char[]) ois.readObject();
+		sLog_fill = ois.readInt();
+		sLog = (short[]) ois.readObject();
+
+		aLog_owners = (String[]) ois.readObject();
+		iLog_owners = (String[]) ois.readObject();
+		jLog_owners = (String[]) ois.readObject();
+		fLog_owners = (String[]) ois.readObject();
+		dLog_owners = (String[]) ois.readObject();
+		bLog_owners = (String[]) ois.readObject();
+		zLog_owners = (String[]) ois.readObject();
+		cLog_owners = (String[]) ois.readObject();
+		sLog_owners = (String[]) ois.readObject();
+
+		ExportedSerializableLog.aLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.iLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.jLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.fLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.dLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.bLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.zLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.cLog_replayIndex = new HashMap<String,Integer>();
+		ExportedSerializableLog.sLog_replayIndex = new HashMap<String,Integer>();
+	}
+}
\ No newline at end of file
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Log.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Log.java
index 95965f8..b7ceeb4 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Log.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/Log.java
@@ -1,92 +1,25 @@
 package edu.columbia.cs.psl.invivo.record;

+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
 public class Log {
 	public static Object[] aLog = new Object[Constants.DEFAULT_LOG_SIZE];
-	public static int[] iLog = new int[Constants.DEFAULT_LOG_SIZE];
-	public static long[] jLog = new long[Constants.DEFAULT_LOG_SIZE];
-	public static float[] fLog = new float[Constants.DEFAULT_LOG_SIZE];
-	public static double[] dLog = new double[Constants.DEFAULT_LOG_SIZE];
-	public static byte[] bLog = new byte[Constants.DEFAULT_LOG_SIZE];
-	public static boolean[] zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
-	public static char[] cLog = new char[Constants.DEFAULT_LOG_SIZE];
-	public static short[] sLog = new short[Constants.DEFAULT_LOG_SIZE];
-	public static Object lock = new Object();
-	public static int aLog_fill, iLog_fill, jLog_fill, fLog_fill, dLog_fill, bLog_fill, zLog_fill, cLog_fill, sLog_fill;
-	public static void growaLog()
-	{
-		Object[] newA = new Object[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(aLog, 0, newA, 0, aLog.length);
-		aLog = newA;
-	}
-	public static void growiLog()
-	{
-		int[] newA = new int[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(iLog, 0, newA, 0, iLog.length);
-		iLog = newA;
-	}
-	public static void growjLog()
-	{
-		long[] newA = new long[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(jLog, 0, newA, 0, jLog.length);
-		jLog = newA;
-	}
-	public static void growfLog()
-	{
-		float[] newA = new float[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(fLog, 0, newA, 0, fLog.length);
-		fLog = newA;
-	}
-	public static void growdLog()
-	{
-		double[] newA = new double[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(dLog, 0, newA, 0, dLog.length);
-		dLog = newA;
-	}
-	public static void growbLog()
-	{
-		byte[] newA = new byte[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(bLog, 0, newA, 0, bLog.length);
-		bLog = newA;
-	}
-	public static void growzLog()
-	{
-		boolean[] newA = new boolean[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(zLog, 0, newA, 0, zLog.length);
-		zLog = newA;
-	}
-	public static void growcLog()
-	{
-		char[] newA = new char[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(cLog, 0, newA, 0, cLog.length);
-		cLog = newA;
-	}
-	public static void growsLog()
-	{
-		short[] newA = new short[(int) (aLog.length * Constants.LOG_GROWTH_RATE)];
-		System.arraycopy(sLog, 0, newA, 0, sLog.length);
-		sLog = newA;
-	}
+	public static String[] aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static Lock logLock = new ReentrantLock();
+//	public static Object lock = new Object();
+	public static int logsize = 0;
+	public static int aLog_fill;
+
+
 	public static void clearLog() {
 //		System.err.println("start cl");
+		logsize = 0;
 		aLog = new Object[Constants.DEFAULT_LOG_SIZE];
-		iLog = new int[Constants.DEFAULT_LOG_SIZE];
-		jLog = new long[Constants.DEFAULT_LOG_SIZE];
-		fLog = new float[Constants.DEFAULT_LOG_SIZE];
-		dLog = new double[Constants.DEFAULT_LOG_SIZE];
-		bLog = new byte[Constants.DEFAULT_LOG_SIZE];
-		zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
-		cLog = new char[Constants.DEFAULT_LOG_SIZE];
-		sLog = new short[Constants.DEFAULT_LOG_SIZE];
+		aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];

 		aLog_fill = 0;
-		iLog_fill = 0;
-		jLog_fill = 0;
-		fLog_fill = 0;
-		dLog_fill = 0;
-		bLog_fill = 0;
-		zLog_fill = 0;
-		cLog_fill = 0;
-		sLog_fill = 0;
+
 //		System.err.println("starting gc");
 //		System.gc();
 //		System.err.println("Fin gc");
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/MethodCall.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/MethodCall.java
index c8a1ad2..1d3094b 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/MethodCall.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/MethodCall.java
@@ -1,5 +1,7 @@
 package edu.columbia.cs.psl.invivo.record;

+import java.util.HashSet;
+
 import org.objectweb.asm.Type;

 public class MethodCall {
@@ -12,6 +14,11 @@ public class MethodCall {
 	private String methodName;
 	private String methodDesc;
 	private boolean isStatic;
+
+	private static HashSet<String> serializableClasses = new HashSet<String>();
+	static{
+		serializableClasses.add(Type.getType(String.class).getInternalName());
+	}
 	public MethodCall(String sourceMethodName, String sourceMethodDesc, String sourceClass, int pc, int lineNumber, String methodOwner, String methodName, String methodDesc, boolean isStatic) {
 		this.sourceMethodName = sourceMethodName;
 		this.sourceMethodDesc = sourceMethodDesc;
@@ -74,6 +81,30 @@ public class MethodCall {
 			return true;
 		return false;
 	}
+	public static String getLogClassName(Type t)
+	{
+		if((t.getSort() != Type.OBJECT  && t.getSort() != Type.ARRAY)|| //primitives
+				(t.getSort() == Type.OBJECT && serializableClasses.contains(t.getInternalName())) || //serializble
+				(t.getSort() == Type.ARRAY && ((t.getElementType().getSort() != Type.OBJECT && t.getElementType().getSort() != Type.ARRAY)|| serializableClasses.contains(t.getElementType().getInternalName())))) // array of prims or array of serializable
+			return Type.getInternalName(SerializableLog.class);
+		else
+			return Type.getInternalName(Log.class);
+	}
+	public static String getReplayClassName(Type t)
+	{
+		if(getLogClassName(t).equals(Type.getInternalName(SerializableLog.class)))
+			return Type.getInternalName(ExportedSerializableLog.class);
+		else
+			return Type.getInternalName(ExportedLog.class);
+	}
+	public String getReplayClassName()
+	{
+		return getReplayClassName(Type.getReturnType(methodDesc));
+	}
+	public String getLogClassName()
+	{
+		return getLogClassName(Type.getReturnType(methodDesc));
+	}
 	public String getCapturePrefix()
 	{
 		String r = sourceMethodName.replace("<", "___").replace(">", "___")+"$$$$"+methodName.replace("<", "___").replace(">", "___")+"$$$$";
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/SerializableLog.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/SerializableLog.java
new file mode 100644
index 0000000..7b0c2db
--- /dev/null
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/SerializableLog.java
@@ -0,0 +1,33 @@
+package edu.columbia.cs.psl.invivo.record;
+
+import java.io.Serializable;
+
+public class SerializableLog implements Serializable{
+
+	private static final long	serialVersionUID	= 4627796984904522647L;
+	public static Object[] aLog = new Object[Constants.DEFAULT_LOG_SIZE];
+
+	public static int[] iLog = new int[Constants.DEFAULT_LOG_SIZE];
+	public static long[] jLog = new long[Constants.DEFAULT_LOG_SIZE];
+	public static float[] fLog = new float[Constants.DEFAULT_LOG_SIZE];
+	public static double[] dLog = new double[Constants.DEFAULT_LOG_SIZE];
+	public static byte[] bLog = new byte[Constants.DEFAULT_LOG_SIZE];
+	public static boolean[] zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
+	public static char[] cLog = new char[Constants.DEFAULT_LOG_SIZE];
+	public static short[] sLog = new short[Constants.DEFAULT_LOG_SIZE];
+
+	public static String[] aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] iLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] jLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] fLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] dLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] bLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] zLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] cLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+	public static String[] sLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+
+	public static int logsize = 0;
+	public static int aLog_fill, iLog_fill, jLog_fill, fLog_fill, dLog_fill, bLog_fill, zLog_fill, cLog_fill, sLog_fill;
+
+
+}
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceExportRunner.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceExportRunner.java
index 82e15e9..fec9ada 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceExportRunner.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceExportRunner.java
@@ -1,7 +1,9 @@
 package edu.columbia.cs.psl.invivo.record;

 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.FileWriter;
+import java.io.ObjectOutputStream;
 import java.lang.reflect.Field;

 import com.thoughtworks.xstream.XStream;
@@ -9,115 +11,212 @@ import com.thoughtworks.xstream.XStream;
 import edu.columbia.cs.psl.invivo.record.xstream.StaticReflectionProvider;

 public class WallaceExportRunner extends Thread {
-	//	static Class<?> logger;
+	// static Class<?> logger;
 	static {
-		//		try {
-		////			System.err.println("Loading log class");
-		//			logger = Class.forName(Constants.LOG_DUMP_CLASS.replace("/", "."));
-		////			System.err.println("Loaded");
-		//		} catch (ClassNotFoundException e) {
-		//			// TODO Auto-generated catch block
-		//			e.printStackTrace();
-		//		}
+		// try {
+		// // System.err.println("Loading log class");
+		// logger = Class.forName(Constants.LOG_DUMP_CLASS.replace("/", "."));
+		// // System.err.println("Loaded");
+		// } catch (ClassNotFoundException e) {
+		// // TODO Auto-generated catch block
+		// e.printStackTrace();
+		// }
 	}

 	@Override
 	public void run() {
-		//		System.err.println("Export runner started");
-				while(1 == 1)
-				{
-		//			System.out.println("Exporting");
-		//			System.err.println("Exporting");
-		//			export(); //TODO uncomment
-		//			System.err.println("Exported");
-		try {
-			//				Thread.sleep(60000); //1 minute
-//			Thread.sleep(300000); //5 minutes
-							Thread.sleep(10000); //10 seconds
-			//				Thread.sleep(5000); //5 seconds
-//							Thread.sleep(1000); //1 seconds
-//							System.out.println("Waking up checking flag");
-							if(shouldExport == 1)
-								export();
-
-		} catch (InterruptedException e) {
-			if(shouldExport == 1)
-				export();
+		// System.err.println("Export runner started");
+		while (1 == 1) {
+			// System.out.println("Exporting");
+			// System.err.println("Exporting");
+			// export(); //TODO uncomment
+			// System.err.println("Exported");
+			try {
+				// Thread.sleep(60000); //1 minute
+				// Thread.sleep(300000); //5 minutes
+				Thread.sleep(10000); // 10 seconds
+				// Thread.sleep(5000); //5 seconds
+				// Thread.sleep(1000); //1 seconds
+				// System.out.println("Waking up checking flag");
+				if (shouldExport == 1)
+					export();
+				if (shouldExportSerializable == 1)
+					exportSerializable();
+				if (shouldExport == 1)
+					export();
+
+			} catch (InterruptedException e) {
+				if (shouldExport == 1)
+					export();
+				if (shouldExportSerializable == 1)
+					exportSerializable();
+				if (shouldExport == 1)
+					export();
+			}
 		}
-				}
 	}
+
 	static WallaceExportRunner inst = new WallaceExportRunner();
+
 	public WallaceExportRunner() {
 		setDaemon(true);
+		setPriority(Thread.MAX_PRIORITY);
 	}

-	private static ExportedLog	log	= new ExportedLog();
-
+	private static ExportedLog log = new ExportedLog();
+
 	public static void export() {
 		shouldExport = 0;
 		try {
 			XStream xstream = new XStream(new StaticReflectionProvider());
 			String xml = "";
-//			System.out.println("Waiting for the lock");
-			synchronized (Log.lock) {
-				ExportedLog.aLog = Log.aLog;
-				ExportedLog.bLog = Log.bLog;
-				ExportedLog.cLog = Log.cLog;
-				ExportedLog.dLog = Log.dLog;
-				ExportedLog.iLog = Log.iLog;
-				ExportedLog.fLog = Log.fLog;
-				ExportedLog.jLog = Log.jLog;
-				ExportedLog.zLog = Log.zLog;
-				ExportedLog.sLog = Log.sLog;
-
-				ExportedLog.aLog_fill = Log.aLog_fill;
-				ExportedLog.bLog_fill = Log.bLog_fill;
-				ExportedLog.cLog_fill = Log.cLog_fill;
-				ExportedLog.dLog_fill = Log.dLog_fill;
-				ExportedLog.iLog_fill = Log.iLog_fill;
-				ExportedLog.fLog_fill = Log.fLog_fill;
-				ExportedLog.jLog_fill = Log.jLog_fill;
-				ExportedLog.zLog_fill = Log.zLog_fill;
-				ExportedLog.sLog_fill = Log.sLog_fill;
-				Log.clearLog();
-			}
-//				System.err.println("Serializing");
-				try{
+			// System.out.println("Waiting for the lock");
+			Log.logLock.lock();
+			ExportedLog.aLog = Log.aLog;
+			ExportedLog.aLog_owners = Log.aLog_owners;
+			ExportedLog.aLog_fill = Log.aLog_fill;
+			Log.logsize = 0;
+			Log.aLog = new Object[Constants.DEFAULT_LOG_SIZE];
+			Log.aLog_fill = 0;
+			Log.logLock.unlock();
+//			System.err.println("Serializing");
+			try {
 				xml = xstream.toXML(log);
-				}
-				catch(Exception ex)
-				{
-					System.err.println("NPE" + ex.getMessage());
-				}
-//				System.err.println("Clearing");
-				ExportedLog.clearLog();
-//				System.err.println("Cleared");
-
-			//CloningUtils.exportLock.writeLock().unlock();
+			} catch (Exception ex) {
+				System.err.println("NPE" + ex.getMessage());
+			}
+			// System.err.println("Clearing");
+			ExportedLog.clearLog();
+			// System.err.println("Cleared");
+
+			// CloningUtils.exportLock.writeLock().unlock();
 			File output = new File("wallace_" + System.currentTimeMillis() + ".log");
 			FileWriter fw = new FileWriter(output);
 			fw.write(xml);
 			fw.close();
+			// synchronized (Log.lock) {
+			// Log.lock.notifyAll();
+			// }
+			// synchronized (Log.lock) {
+			// Log.lock.notifyAll();
+			// }

 		} catch (Exception exi) {
-//			System.err.println(exi.getMessage());
+			// System.err.println(exi.getMessage());
 		}
 		shouldExport = -1;
 	}

-	private static int	shouldExport	= -1;
+	private static ExportedSerializableLog logS = new ExportedSerializableLog();
+
+	public static void exportSerializable() {
+		shouldExportSerializable = 0;
+		try {
+
+			Log.logLock.lock();
+			{
+				ExportedSerializableLog.aLog = SerializableLog.aLog;
+				ExportedSerializableLog.aLog_fill = SerializableLog.aLog_fill;
+				ExportedSerializableLog.bLog = SerializableLog.bLog;
+				ExportedSerializableLog.cLog = SerializableLog.cLog;
+				ExportedSerializableLog.dLog = SerializableLog.dLog;
+				ExportedSerializableLog.iLog = SerializableLog.iLog;
+				ExportedSerializableLog.fLog = SerializableLog.fLog;
+				ExportedSerializableLog.jLog = SerializableLog.jLog;
+				ExportedSerializableLog.zLog = SerializableLog.zLog;
+				ExportedSerializableLog.sLog = SerializableLog.sLog;
+
+				ExportedSerializableLog.bLog_fill = SerializableLog.bLog_fill;
+				ExportedSerializableLog.cLog_fill = SerializableLog.cLog_fill;
+				ExportedSerializableLog.dLog_fill = SerializableLog.dLog_fill;
+				ExportedSerializableLog.iLog_fill = SerializableLog.iLog_fill;
+				ExportedSerializableLog.fLog_fill = SerializableLog.fLog_fill;
+				ExportedSerializableLog.jLog_fill = SerializableLog.jLog_fill;
+				ExportedSerializableLog.zLog_fill = SerializableLog.zLog_fill;
+				ExportedSerializableLog.sLog_fill = SerializableLog.sLog_fill;
+
+				ExportedSerializableLog.aLog_owners = SerializableLog.aLog_owners;
+				ExportedSerializableLog.iLog_owners = SerializableLog.iLog_owners;
+				ExportedSerializableLog.jLog_owners = SerializableLog.jLog_owners;
+				ExportedSerializableLog.fLog_owners = SerializableLog.fLog_owners;
+				ExportedSerializableLog.dLog_owners = SerializableLog.dLog_owners;
+				ExportedSerializableLog.bLog_owners = SerializableLog.bLog_owners;
+				ExportedSerializableLog.zLog_owners = SerializableLog.zLog_owners;
+				ExportedSerializableLog.cLog_owners = SerializableLog.cLog_owners;
+				ExportedSerializableLog.sLog_owners = SerializableLog.sLog_owners;
+
+				SerializableLog.aLog = new Object[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.iLog = new int[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.jLog = new long[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.fLog = new float[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.dLog = new double[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.bLog = new byte[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.zLog = new boolean[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.cLog = new char[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.sLog = new short[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.iLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.jLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.fLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.dLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.bLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.zLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.cLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.sLog_owners = new String[Constants.DEFAULT_LOG_SIZE];
+				SerializableLog.logsize = 0;
+				SerializableLog.iLog_fill = 0;
+				SerializableLog.jLog_fill = 0;
+				SerializableLog.fLog_fill = 0;
+				SerializableLog.dLog_fill = 0;
+				SerializableLog.bLog_fill = 0;
+				SerializableLog.zLog_fill = 0;
+				SerializableLog.cLog_fill = 0;
+				SerializableLog.sLog_fill = 0;
+				SerializableLog.aLog_fill = 0;
+			}
+			Log.logLock.unlock();
+			// System.err.println("Serializing serializable");
+			File output = new File("wallace_serializable_" + System.currentTimeMillis() + ".log");
+
+			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(output));
+			oos.writeObject(logS);
+			oos.flush();
+			oos.close();
+			// System.err.println("Clearing serializable");
+			ExportedLog.clearLog();
+			// System.err.println("Cleared serializable");
+			// System.out.println("Notifying; " + Log.logsize
+			// +";"+SerializableLog.logsize);
+			// synchronized (Log.lock) {
+			// Log.lock.notifyAll();
+			// }
+			// synchronized (Log.lock) {
+			// Log.lock.notifyAll();
+			// }
+		} catch (Exception exi) {
+			// System.err.println(exi.getMessage());
+		}
+		shouldExportSerializable = -1;
+	}
+
+	private static int shouldExport = -1;
+	private static int shouldExportSerializable = -1;
+
+	public static void _exportSerializable() {
+		if (shouldExportSerializable == -1) {
+			// System.out.println("Flagged shouldexport serializble");
+			Thread.yield();
+			shouldExportSerializable = 1;
+			inst.interrupt();
+		}
+	}

 	public static void _export() {
-//		System.err.println("flag export");
-		if(shouldExport == -1)
-		{
+		if (shouldExport == -1) {
+			Thread.yield();
 			shouldExport = 1;
 			inst.interrupt();
 		}
-//		if(inst.isAlive())
-//			System.out.println("Alive still!");
-//		else
-//			System.out.println("Its dead");
 	}

 }
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceUncaughtExceptionHandler.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceUncaughtExceptionHandler.java
index 2923928..602df4e 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceUncaughtExceptionHandler.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/WallaceUncaughtExceptionHandler.java
@@ -16,6 +16,7 @@ public class WallaceUncaughtExceptionHandler implements Thread.UncaughtException
 			e.printStackTrace();
 			System.err.println("Writing log");
 			WallaceExportRunner.export();
+			WallaceExportRunner.exportSerializable();
 			}
 		catch(Exception exi)
 		{
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/CloningAdviceAdapter.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/CloningAdviceAdapter.java
index 53b4df3..a07d50d 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/CloningAdviceAdapter.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/CloningAdviceAdapter.java
@@ -10,6 +10,7 @@ import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.AdviceAdapter;
 import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.LocalVariablesSorter;
 import org.objectweb.asm.commons.Method;
 import org.objectweb.asm.tree.FieldNode;

@@ -17,14 +18,15 @@ import edu.columbia.cs.psl.invivo.record.CloningUtils;
 import edu.columbia.cs.psl.invivo.record.Constants;
 import edu.columbia.cs.psl.invivo.record.Instrumenter;
 import edu.columbia.cs.psl.invivo.record.Log;
+import edu.columbia.cs.psl.invivo.record.SerializableLog;
 import edu.columbia.cs.psl.invivo.record.WallaceExportRunner;

 public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {

-	private static final HashSet<String>	ignoredClasses		= new HashSet<String>();
-	private static boolean					flexibleLog			= false;
+	private static final HashSet<String> ignoredClasses = new HashSet<String>();
+	private static boolean flexibleLog = false;

-	private static final HashSet<String>	immutableClasses	= new HashSet<String>();
+	private static final HashSet<String> immutableClasses = new HashSet<String>();
 	static {
 		immutableClasses.add("Ljava/lang/Integer;");
 		immutableClasses.add("Ljava/lang/Long;");
@@ -52,345 +54,32 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 		immutableClasses.add("L");

 	}
-	private String							className;
+	private String className;

-	public CloningAdviceAdapter(int api, MethodVisitor mv, int access, String name, String desc, String classname) {
+	private LocalVariablesSorter lvsorter;
+
+	public CloningAdviceAdapter(int api, MethodVisitor mv, int access, String name, String desc, String classname, LocalVariablesSorter lvsorter) {
 		super(api, mv, access, name, desc);
 		this.className = classname;
-	}
-
-	public void fastCloneList(String fieldName, String fieldDesc) {
-		/* Null check */
-		super.visitVarInsn(Opcodes.ALOAD, 0);
-		super.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, "Ljava/util/ArrayList;");
-		Label ifNull = new Label();
-		super.visitJumpInsn(Opcodes.IFNULL, ifNull);
-		Label notNull = new Label();
-		super.visitLabel(notNull);
-
-		/* Instantiation */
-		super.visitVarInsn(Opcodes.ALOAD, 1);
-		super.visitTypeInsn(Opcodes.NEW, "java/util/ArrayList");
-		super.visitInsn(Opcodes.DUP);
-		super.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V");
-		super.visitFieldInsn(PUTFIELD, className, fieldName, "Ljava/util/ArrayList;");
-
-		loadThis();
-		super.visitFieldInsn(GETFIELD, className, fieldName, "Ljava/util/ArrayList;");
-		super.visitMethodInsn(INVOKEVIRTUAL, "java/util/ArrayList", "iterator", "()Ljava/util/Iterator;");
-		super.visitVarInsn(ASTORE, 3);
-		Label l6 = new Label();
-		super.visitJumpInsn(GOTO, l6);
-		Label l7 = new Label();
-		super.visitLabel(l7);
-		// super.visitFrame(Opcodes.F_FULL, 4, new Object[] { className, className,
-		// Opcodes.TOP, "java/util/Iterator" }, 0, new Object[] {});
-		super.visitVarInsn(ALOAD, 3);
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
-		super.visitTypeInsn(CHECKCAST, fieldDesc);
-		super.visitVarInsn(ASTORE, 2);
-
-		super.visitVarInsn(ALOAD, 1);
-		super.visitFieldInsn(GETFIELD, className, fieldName, "Ljava/util/ArrayList;");
-		super.visitVarInsn(ALOAD, 2);
-		visitMethodInsn(INVOKEVIRTUAL, className, Constants.INNER_COPY_METHOD_NAME, "()" + fieldDesc);
-		super.visitMethodInsn(INVOKEVIRTUAL, "java/util/ArrayList", "add", "(Ljava/lang/Object;)Z");
-		super.visitInsn(POP);
-		// super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
-		super.visitVarInsn(ALOAD, 3);
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
-		super.visitJumpInsn(IFNE, l7);
-		super.visitLabel(ifNull);
-		// super.visitFrame(Opcodes.F_FULL, 2, new Object[] { className, className
-		// }, 0, new Object[] {});
-	}
-
-	public void fastCloneMap(String fieldName, String keyDesc, String valueDesc) {
-		/* Null check */
-		loadThis();
-		super.visitFieldInsn(GETFIELD, className, fieldName, "Ljava/util/HashMap;");
-		Label l2 = new Label();
-		super.visitJumpInsn(IFNULL, l2);
-		Label l3 = new Label();
-		super.visitLabel(l3);
-
-		/* Instantiate the hashmap */
-		super.visitVarInsn(ALOAD, 1);
-		super.visitTypeInsn(NEW, "java/util/HashMap");
-		super.visitInsn(DUP);
-		super.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V");
-		super.visitFieldInsn(PUTFIELD, className, fieldName, "Ljava/util/HashMap;");
-
-		/* Copy the entries */
-		loadThis();
-		super.visitFieldInsn(GETFIELD, className, fieldName, "Ljava/util/HashMap;");
-		super.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "entrySet", "()Ljava/util/Set;");
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "iterator", "()Ljava/util/Iterator;");
-		super.visitVarInsn(ASTORE, 3);
-		Label l5 = new Label();
-		super.visitJumpInsn(GOTO, l5);
-		Label l6 = new Label();
-		super.visitLabel(l6);
-		// super.visitFrame(Opcodes.F_FULL, 4, new Object[] { className, className,
-		// Opcodes.TOP, "java/util/Iterator" }, 0, new Object[] {});
-		super.visitVarInsn(ALOAD, 3);
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;");
-		super.visitTypeInsn(CHECKCAST, "java/util/Map$Entry");
-		super.visitVarInsn(ASTORE, 2);
-
-		super.visitVarInsn(ALOAD, 1);
-		super.visitFieldInsn(GETFIELD, className, fieldName, "Ljava/util/HashMap;");
-		super.visitVarInsn(ALOAD, 2);
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Map$Entry", "getKey", "()Ljava/lang/Object;");
-		super.visitTypeInsn(CHECKCAST, keyDesc);
-		/* Put in the checks here or the call to copy */
-		super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "toString", "()Ljava/lang/String;");
-		super.visitVarInsn(ALOAD, 2);
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Map$Entry", "getValue", "()Ljava/lang/Object;");
-		super.visitTypeInsn(CHECKCAST, valueDesc);
-		/* Put in the checks here or the call to copy */
-		super.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-		super.visitInsn(POP);
-		super.visitLabel(l5);
-		// super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
-		super.visitVarInsn(ALOAD, 3);
-		super.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z");
-		super.visitJumpInsn(IFNE, l6);
-		super.visitLabel(l2);
-		// super.visitFrame(Opcodes.F_FULL, 2, new Object[] { className, className
-		// }, 0, new Object[] {});
-	}
-
-	public static void fastCloneSet() {
-
-	}
-
-	public static void fastCloneQueue() {
-
-	}
-
-	protected void generateOuterCopyMethod() {
-		super.visitTypeInsn(NEW, "java/util/IdentityHashMap");
-		super.visitInsn(DUP);
-		super.visitMethodInsn(INVOKESPECIAL, "java/util/IdentityHashMap", "<init>", "()V");
-		super.visitFieldInsn(PUTSTATIC, "edu/columbia/cs/psl/invivo/record/CloningUtils", "cloneCache", "Ljava/util/IdentityHashMap;");
-		loadThis();
-		super.visitMethodInsn(INVOKEVIRTUAL, className, Constants.INNER_COPY_METHOD_NAME, "()L" + className + ";");
-	}
-
-	protected void generateCopyMethod() {
-		if (Instrumenter.instrumentedClasses.containsKey(className)) {
-
-			/* If what we are looking for is cached, just return that */
-
-			super.visitFieldInsn(GETSTATIC, "edu/columbia/cs/psl/invivo/record/CloningUtils", "cloneCache", "Ljava/util/IdentityHashMap;");
-			loadThis();
-			super.visitMethodInsn(INVOKEVIRTUAL, "java/util/IdentityHashMap", "containsKey", "(Ljava/lang/Object;)Z");
-			Label notCached = new Label();
-			super.visitJumpInsn(IFEQ, notCached);
-			super.visitFieldInsn(GETSTATIC, "edu/columbia/cs/psl/invivo/record/CloningUtils", "cloneCache", "Ljava/util/IdentityHashMap;");
-			loadThis();
-			super.visitMethodInsn(INVOKEVIRTUAL, "java/util/IdentityHashMap", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
-			super.visitTypeInsn(CHECKCAST, className);
-			super.visitInsn(ARETURN);
-			super.visitLabel(notCached);
-
-			Label varStart = new Label();
-			visitLabel(varStart);
-			int localVar = this.newLocal(Type.getType("L" + className + ";"));
-
-			/* 1) Call the clone constructor */
-			loadThis();
-			visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "clone", "()Ljava/lang/Object;");
-			visitTypeInsn(CHECKCAST, className);
-			visitVarInsn(ASTORE, localVar);
-
-			loadThis();
-			visitVarInsn(ALOAD, localVar);
-			visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, Constants.SET_FIELDS_METHOD_NAME, "(L" + className + ";)L" + className + ";");
-
-			Label varEnd = new Label();
-			visitLabel(varEnd);
-			visitLocalVariable("myClone", "L" + className + ";", null, varStart, varEnd, localVar);
-		} else {
-			loadThis();
-			cloneValAtTopOfStack("L" + className + ";");
-		}
-	}
-
-	private boolean isCollection(String desc) {
-		if (desc.contains("ArrayList") || desc.contains("HashMap"))
-			return true;
-		return false;
-	}
-
-	public void generateSetFieldsMethod() {
-
-		/*
-		 * 2) For each field do the following a) If its a primitive simply copy it b) If its an object, call the respective ._copy method iff its a
-		 * class we have instrumented c) If its an array, create a loop and do steps a) and b) d) If its a collection, take care of that e) If nothing
-		 * works, call the reflection cloning util
-		 */
-		int cloneVar = 1;
-		int iteratorVar = this.newLocal(Type.getType(Integer.class));
-		for (Object o : Instrumenter.instrumentedClasses.get(className).fields) {
-			FieldNode f = (FieldNode) o;
-			Type fieldType = Type.getType(f.desc);
-			if (immutableClasses.contains(fieldType.getDescriptor())) {
-				visitVarInsn(ALOAD, cloneVar);
-				loadThis();
-				visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor()); // Put
-																						// L
-																						// and
-																						// ;
-																						// in
-																						// front
-																						// and
-																						// back
-																						// of
-																						// getname
-				visitFieldInsn(PUTFIELD, className, f.name, fieldType.getDescriptor());
-			} else if (fieldType.getSort() == Type.OBJECT && (Instrumenter.instrumentedClasses.containsKey(fieldType.getClassName()))) {
-				loadThis();
-				visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-				Label nullContinue = new Label();
-				visitJumpInsn(IFNULL, nullContinue);
-				Label nonNull = new Label();
-				visitLabel(nonNull);
-
-				visitVarInsn(ALOAD, cloneVar);
-				loadThis();
-				visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-				visitMethodInsn(INVOKEVIRTUAL, fieldType.getInternalName(), Constants.INNER_COPY_METHOD_NAME, "()" + fieldType.getDescriptor());
-				visitFieldInsn(PUTFIELD, className, f.name, fieldType.getDescriptor());
-				visitLabel(nullContinue);
-			} else if (fieldType.getSort() == Type.ARRAY) {
-				/* Check if non null */
-				loadThis();
-				visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-				Label nullContinue = new Label();
-				visitJumpInsn(IFNULL, nullContinue);
-				Label nonNull = new Label();
-				visitLabel(nonNull);
-
-				/* Instantiate new array */
-				String arrayTypeDescriptor = fieldType.getDescriptor().replace("[L", "L");
-
-				visitVarInsn(ALOAD, cloneVar);
-				loadThis();
-				visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-				visitInsn(ARRAYLENGTH);
-				visitTypeInsn(ANEWARRAY, arrayTypeDescriptor);
-				visitFieldInsn(PUTFIELD, className, f.name, fieldType.getDescriptor());
-
-				/* Start copying */
-				// TODO: Do a system.arraycopy if its an array of immutables
-				if (immutableClasses.contains(fieldType.getElementType().getDescriptor())) {
-					loadThis();
-					super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-					super.visitInsn(ICONST_0);
-					super.visitVarInsn(ALOAD, cloneVar);
-					super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-					super.visitInsn(ICONST_0);
-					loadThis();
-					super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-					super.visitInsn(ARRAYLENGTH);
-					super.visitMethodInsn(INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
-				} else {
-
-					super.visitInsn(ICONST_0);
-					super.visitVarInsn(ISTORE, iteratorVar);
-
-					Label l7 = new Label();
-					super.visitJumpInsn(GOTO, l7);
-					Label l8 = new Label();
-					super.visitLabel(l8);
-					// super.visitFrame(Opcodes.F_APPEND, 2, new Object[] {
-					// className, Opcodes.INTEGER }, 0, null);
-					super.visitVarInsn(ALOAD, cloneVar);
-					super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-					super.visitVarInsn(ILOAD, iteratorVar);
-					loadThis();
-					super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-					super.visitVarInsn(ILOAD, iteratorVar);
-					super.visitInsn(AALOAD);
-
-					generateCloneInner(arrayTypeDescriptor);
-
-					super.visitInsn(AASTORE);
-					super.visitIincInsn(2, 1);
-					super.visitLabel(l7);
-					// super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
-					super.visitVarInsn(ILOAD, iteratorVar);
-					super.visitVarInsn(ALOAD, cloneVar);
-					super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-					super.visitInsn(ARRAYLENGTH);
-					super.visitJumpInsn(IF_ICMPLT, l8);
-
-					Label doneCopying = new Label();
-					super.visitLabel(doneCopying);
-					// super.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
-				}
-				visitLabel(nullContinue);
-			} else if (this.isCollection(className)) {
-				if (className.contains("HashMap")) {
-					String hashMapDesc = fieldType.getDescriptor();
-					String entryDesc = hashMapDesc.substring(hashMapDesc.indexOf("<") + 1, hashMapDesc.lastIndexOf(">"));
-					this.fastCloneMap(f.name, entryDesc.split(";")[0], entryDesc.split(";")[1]);
-				} else if (className.contains("ArrayList")) {
-					String hashMapDesc = fieldType.getDescriptor();
-					String entryDesc = hashMapDesc.substring(hashMapDesc.indexOf("<") + 1, hashMapDesc.lastIndexOf(">"));
-					this.fastCloneList(f.name, entryDesc);
-				}
-			} else {
-				/* All else fails, just call the reflective cloning */
-				super.visitVarInsn(ALOAD, cloneVar);
-				super.visitFieldInsn(GETSTATIC, "edu/columbia/cs/psl/invivo/record/CloningUtils", "cloner", "Lcom/rits/cloning/Cloner;");
-				loadThis();
-				super.visitFieldInsn(GETFIELD, className, f.name, fieldType.getDescriptor());
-				super.visitMethodInsn(INVOKEVIRTUAL, "com/rits/cloning/Cloner", "deepClone", "(Ljava/lang/Object;)Ljava/lang/Object;");
-				super.visitTypeInsn(CHECKCAST, fieldType.getClassName().replace(".", "/"));
-				super.visitFieldInsn(PUTFIELD, className, f.name, fieldType.getDescriptor());
-			}
-		}
-
-		/*
-		 * If the super class is instrumented, we should probably call that as well
-		 */
-
-		String parent = Instrumenter.instrumentedClasses.get(className).superName;
-		if (Instrumenter.instrumentedClasses.containsKey(parent)) {
-			loadThis();
-			super.visitVarInsn(ALOAD, cloneVar);
-			super.visitMethodInsn(INVOKESPECIAL, parent, Constants.SET_FIELDS_METHOD_NAME, "(L" + parent + ";)L" + parent + ";");
-			super.visitInsn(POP);
-		}
-
-		/* We are done, put the result in the cache */
-		super.visitFieldInsn(GETSTATIC, "edu/columbia/cs/psl/invivo/record/CloningUtils", "cloneCache", "Ljava/util/IdentityHashMap;");
-		super.visitVarInsn(ALOAD, cloneVar);
-		super.visitVarInsn(ALOAD, cloneVar);
-		super.visitMethodInsn(INVOKEVIRTUAL, "java/util/IdentityHashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-		super.visitInsn(POP);
-
-		visitVarInsn(ALOAD, cloneVar);
+		this.lvsorter = lvsorter;
 	}

 	/**
-	 * Precondition: Current element at the top of the stack is the element we need cloned Post condition: Current element at the top of the stack is
+	 * Precondition: Current element at the top of the stack is the element we
+	 * need cloned Post condition: Current element at the top of the stack is
 	 * the cloned element (and non-cloned is removed)
 	 */

 	protected void cloneValAtTopOfStack(String typeOfField) {
-		_generateClone(typeOfField, Constants.OUTER_COPY_METHOD_NAME, null);
+		_generateClone(typeOfField, Constants.OUTER_COPY_METHOD_NAME, null, false);
 	}

-	protected void cloneValAtTopOfStack(String typeOfField, String debug) {
-		_generateClone(typeOfField, Constants.OUTER_COPY_METHOD_NAME, debug);
+	protected void cloneValAtTopOfStack(String typeOfField, String debug, boolean secondElHasArrayLen) {
+		_generateClone(typeOfField, Constants.OUTER_COPY_METHOD_NAME, debug, secondElHasArrayLen);
 	}

 	protected void generateCloneInner(String typeOfField) {
-		_generateClone(typeOfField, Constants.INNER_COPY_METHOD_NAME, null);
+		_generateClone(typeOfField, Constants.INNER_COPY_METHOD_NAME, null, false);
 	}

 	public void println(String toPrint) {
@@ -404,29 +93,41 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 		super.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
 	}

-	private void _generateClone(String typeOfField, String copyMethodToCall, String debug) {
+	private void _generateClone(String typeOfField, String copyMethodToCall, String debug, boolean secondElHasArrayLen) {
 		Type fieldType = Type.getType(typeOfField);

 		if (
-//				fieldType.getSort() == Type.ARRAY && fieldType.getElementType().getSort()
-//				||
-				fieldType.getSort() == Type.VOID ||
-				(fieldType.getSort() != Type.ARRAY && (fieldType.getSort() != Type.OBJECT || immutableClasses.contains(typeOfField)))) {
-//			println("reference> " + debug);
-//						println(debug);
-			//			println("Doing nothing");
+		// fieldType.getSort() == Type.ARRAY &&
+		// fieldType.getElementType().getSort()
+		// ||
+		fieldType.getSort() == Type.VOID || (fieldType.getSort() != Type.ARRAY && (fieldType.getSort() != Type.OBJECT || immutableClasses.contains(typeOfField)))) {
+			// println("reference> " + debug);
+			// println(debug);
+			// println("Doing nothing");
 			return;
 		}
 		if (fieldType.getSort() == Type.ARRAY) {
 			if (fieldType.getElementType().getSort() != Type.OBJECT || immutableClasses.contains(fieldType.getElementType().getDescriptor())) {
-//				println("array> " + debug);
+				// println("array> " + debug);

 				// Just need to duplicate the array
 				dup();
 				Label nullContinue = new Label();
 				ifNull(nullContinue);
-				dup();
-				visitInsn(ARRAYLENGTH);
+				if (secondElHasArrayLen) {
+					swap();
+					// pop();
+					// swap();
+					// dup();
+					// visitFieldInsn(GETSTATIC, "java/lang/System", "out",
+					// "Ljava/io/PrintStream;");
+					// swap();
+					// super.visitMethodInsn(INVOKEVIRTUAL,
+					// "java/io/PrintStream", "println", "(I)V");
+				} else {
+					dup();
+					visitInsn(ARRAYLENGTH);
+				}
 				dup();
 				newArray(Type.getType(fieldType.getDescriptor().substring(1)));
 				dupX2();
@@ -435,125 +136,143 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 				dupX2();
 				swap();
 				super.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
-				visitLabel(nullContinue);
+				Label noNeedToPop = new Label();
+				if (secondElHasArrayLen) {
+					visitJumpInsn(GOTO, noNeedToPop);
+					visitLabel(nullContinue);
+					swap();
+					pop();
+				} else {
+					visitLabel(nullContinue);
+				}
+
+				visitLabel(noNeedToPop);

 			} else {
-//				println("heavy> " + debug);
+				// println("heavy> " + debug);
 				// Just use the reflective cloner
 				visitLdcInsn(debug);
 				invokeStatic(Type.getType(CloningUtils.class), Method.getMethod("Object clone(Object, String)"));
 				checkCast(fieldType);
 			}
-		} else if (fieldType.getClassName().contains("InputStream") || fieldType.getClassName().contains("OutputStream")
-				|| fieldType.getClassName().contains("Socket")) {
-			//Do nothing
+		} else if (fieldType.getClassName().contains("InputStream") || fieldType.getClassName().contains("OutputStream") || fieldType.getClassName().contains("Socket")) {
+			// Do nothing
 		} else {
-//			println("heavy> " + debug);
+			// println("heavy> " + debug);
 			visitLdcInsn(debug);
 			invokeStatic(Type.getType(CloningUtils.class), Method.getMethod("Object clone(Object, String)"));
 			checkCast(fieldType);

 		}
 	}
-
-	//	private static Object[] ar;
-//		private void magic()
-//		{
-//			new WallaceExportRunner().
-//		}
-	protected void logValueAtTopOfStackToArray(String logFieldOwner, String logFieldName, String logFieldTypeDesc, Type elementType,
-			boolean isStaticLoggingField, String debug) {
+
+	// private static Object[] ar;
+	// private void magic()
+	// {
+	// new WallaceExportRunner().
+	// }
+	protected void logValueAtTopOfStackToArray(String logFieldOwner, String logFieldName, String logFieldTypeDesc, Type elementType, boolean isStaticLoggingField, String debug,
+			boolean secondElHasArrayLen) {
 		int getOpcode = (isStaticLoggingField ? Opcodes.GETSTATIC : Opcodes.GETFIELD);
 		int putOpcode = (isStaticLoggingField ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD);
-		Label monitorStart = new Label();
-		Label monitorEndLabel = new Label();
-		int monitorIndx = 0;
-
-//		if (threadSafe) {
-			newLocal(Type.getType(logFieldTypeDesc)); //Needed for some reason, unkown? Don't remove though, otherwise ASM messes stuff up
-			newLocal(Type.getType(logFieldTypeDesc)); //Needed for some reason, unkown? Don't remove though, otherwise ASM messes stuff up
-			newLocal(Type.getType(logFieldTypeDesc)); //Needed for some reason, unkown? Don't remove though, otherwise ASM messes stuff up
-			newLocal(Type.getType(logFieldTypeDesc)); //Needed for some reason, unkown? Don't remove though, otherwise ASM messes stuff up
-			newLocal(Type.getType(logFieldTypeDesc)); //Needed for some reason, unkown? Don't remove though, otherwise ASM messes stuff up
-			newLocal(Type.getType(logFieldTypeDesc)); //Needed for some reason, unkown? Don't remove though, otherwise ASM messes stuff up
-			monitorIndx = newLocal(Type.getType("Ljava/lang/Object;"));
-			visitLabel(monitorStart);
-
-			//Lock
-			super.visitFieldInsn(Opcodes.GETSTATIC, logFieldOwner, "lock", "Ljava/lang/Object;");
-			dup();
-			super.visitVarInsn(ASTORE, monitorIndx);
-			super.monitorEnter();
-//		}
-		//Also acquire a read lock for the export lock
-		//		super.visitFieldInsn(GETSTATIC, Type.getInternalName(CloningUtils.class), "exportLock", Type.getDescriptor(ReadWriteLock.class));
-		//		super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(ReadWriteLock.class), "readLock", "()Ljava/util/concurrent/locks/Lock;");
-		//		super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "lock", "()V");

-
+		//Lock
+		super.visitFieldInsn(GETSTATIC, Type.getInternalName(Log.class), "logLock", Type.getDescriptor(Lock.class));
+		super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "lock", "()V");
+
 		// Grow the array if necessary
-		if (!isStaticLoggingField)
-			loadThis();
+
 		super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
-		if (!isStaticLoggingField)
-			loadThis();
 		super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
 		super.arrayLength();
 		Label labelForNoNeedToGrow = new Label();
 		super.ifCmp(Type.INT_TYPE, Opcodes.IFNE, labelForNoNeedToGrow);
 		// In this case, it's necessary to grow it
-			// Create the new array and initialize its size
-//		super.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Log.class), "grow"+logFieldName, "()V");
-
-		int newArray = newLocal(Type.getType(logFieldTypeDesc));
-		if (!isStaticLoggingField)
-			loadThis();
-		super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
-		super.arrayLength();
-		super.visitInsn(Opcodes.I2D);
-		super.visitLdcInsn(Constants.LOG_GROWTH_RATE);
-		super.visitInsn(Opcodes.DMUL);
-		super.visitInsn(Opcodes.D2I);
-
-		super.newArray(Type.getType(logFieldTypeDesc.substring(1))); // Bug in
-																		// ASM
-																		// prevents
-																		// us
-																		// from
-																		// doing
-																		// type.getElementType
-		super.storeLocal(newArray, Type.getType(logFieldTypeDesc));
-		// Do the copy
-		if (!isStaticLoggingField)
-			loadThis();
-		super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
-		super.visitInsn(Opcodes.ICONST_0);
-		super.loadLocal(newArray);
-		super.visitInsn(Opcodes.ICONST_0);
-		if (!isStaticLoggingField)
-			super.loadThis();
-		super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
-		super.arrayLength();
-		super.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
+		// Create the new array and initialize its size
+
+		int newArray = lvsorter.newLocal(Type.getType(logFieldTypeDesc));
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
+		arrayLength();
+		visitInsn(Opcodes.I2D);
+		visitLdcInsn(Constants.LOG_GROWTH_RATE);
+		visitInsn(Opcodes.DMUL);
+		visitInsn(Opcodes.D2I);
+
+		newArray(Type.getType(logFieldTypeDesc.substring(1))); // Bug in
+																// ASM
+																// prevents
+																// us
+																// from
+																// doing
+																// type.getElementType
+		storeLocal(newArray, Type.getType(logFieldTypeDesc));
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
+		visitInsn(Opcodes.ICONST_0);
+		loadLocal(newArray);
+		visitInsn(Opcodes.ICONST_0);
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
+		arrayLength();
+		visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
+
+		// array = newarray
+
+		loadLocal(newArray);
+		visitFieldInsn(putOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
+
+		int newArray2 = lvsorter.newLocal(Type.getType("[Ljava/lang/String;"));
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName+"_owners", "[Ljava/lang/String;");
+		arrayLength();
+		visitInsn(Opcodes.I2D);
+		visitLdcInsn(Constants.LOG_GROWTH_RATE);
+		visitInsn(Opcodes.DMUL);
+		visitInsn(Opcodes.D2I);
+
+		newArray(Type.getType("Ljava/lang/String;"));
+
+		storeLocal(newArray2, Type.getType("[Ljava/lang/String;"));
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName+"_owners", "[Ljava/lang/String;");
+		visitInsn(Opcodes.ICONST_0);
+		loadLocal(newArray2);
+		visitInsn(Opcodes.ICONST_0);
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName+"_owners", "[Ljava/lang/String;");
+		arrayLength();
+		visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");

 		// array = newarray
-		if (!isStaticLoggingField)
-			super.loadThis();
-		super.loadLocal(newArray);
-		super.visitFieldInsn(putOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
-
+
+		loadLocal(newArray2);
+		visitFieldInsn(putOpcode, logFieldOwner, logFieldName+"_owners", "[Ljava/lang/String;");
+
 		visitLabel(labelForNoNeedToGrow);
 		// Load this into the end piece of the array
 		if (elementType.getSize() == 1) {
-			dup();
-			if (!isStaticLoggingField)
-				super.loadThis();
-			super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
-			swap();
-			if (!isStaticLoggingField)
-				super.loadThis();
-			super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
-			swap();
+			if (secondElHasArrayLen) {
+				/*
+				 * size buf
+				 */
+				dupX1();
+				/*
+				 * buf size buf
+				 */
+				visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
+				dupX2();
+				pop();
+				/*
+				 * buf logfield size buf
+				 */
+				visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
+				dupX2();
+				pop();
+				/*
+				 * buf logfield logsize size buf
+				 */
+			} else {
+				dup();
+				visitFieldInsn(getOpcode, logFieldOwner, logFieldName, logFieldTypeDesc);
+				swap();
+				visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
+				swap();
+			}
 		} else if (elementType.getSize() == 2) {
 			dup2();
 			if (!isStaticLoggingField)
@@ -567,45 +286,92 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 			dupX2();
 			pop();
 		}
-		cloneValAtTopOfStack(elementType.getDescriptor(), debug);
+		cloneValAtTopOfStack(elementType.getDescriptor(), debug, secondElHasArrayLen);

-		super.arrayStore(elementType);
+		arrayStore(elementType);
+
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName+"_owners", "[Ljava/lang/String;");
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());

-		if (!isStaticLoggingField)
-			super.loadThis();
-		if (!isStaticLoggingField)
-			super.dup();
-		super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
+		visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;");
+		visitMethodInsn(INVOKEVIRTUAL, "java/lang/Thread", "getName", "()Ljava/lang/String;");
+		arrayStore(Type.getType(String.class));
+		visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());

 		super.visitInsn(Opcodes.ICONST_1);
 		super.visitInsn(Opcodes.IADD);
 		super.visitFieldInsn(putOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
-		//		println("Incremented fill for " + logFieldOwner+"."+logFieldName);
-		//Release the export lock
-		//		super.visitFieldInsn(GETSTATIC, Type.getInternalName(CloningUtils.class), "exportLock", Type.getDescriptor(ReadWriteLock.class));
-		//		super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(ReadWriteLock.class), "readLock", "()Ljava/util/concurrent/locks/Lock;");
-		//		super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "unlock", "()V");
-
-//		if (threadSafe) {
-			//Unlock
-			super.visitVarInsn(ALOAD, monitorIndx);
-			super.monitorExit();
-			visitLabel(monitorEndLabel);
-			Label endLbl = new Label();
-			super.visitFieldInsn(getOpcode, logFieldOwner, logFieldName + "_fill", Type.INT_TYPE.getDescriptor());
-			super.visitLdcInsn(Constants.MAX_LOG_SIZE);
-			super.ifCmp(Type.INT_TYPE, Opcodes.IFNE, endLbl);
+		// println("Incremented fill for " + logFieldOwner+"."+logFieldName);
+		// Release the export lock
+		// super.visitFieldInsn(GETSTATIC,
+		// Type.getInternalName(CloningUtils.class), "exportLock",
+		// Type.getDescriptor(ReadWriteLock.class));
+		// super.visitMethodInsn(INVOKEINTERFACE,
+		// Type.getInternalName(ReadWriteLock.class), "readLock",
+		// "()Ljava/util/concurrent/locks/Lock;");
+		// super.visitMethodInsn(INVOKEINTERFACE,
+		// Type.getInternalName(Lock.class), "unlock", "()V");
+
+		// if (threadSafe) {
+		// Unlock
+		// super.visitVarInsn(ALOAD, monitorIndx);
+		// super.monitorExit();
+		// visitLabel(monitorEndLabel);
+		Label endLbl = new Label();
+
+//		if (elementType.getSort() == Type.ARRAY) {
+//			super.visitInsn(DUP);
+//			super.visitInsn(ARRAYLENGTH);
+//		} else
+			super.visitInsn(ICONST_1);
+		// super.visitVarInsn(ALOAD, monitorIndx);
+		// super.monitorEnter();
+		super.visitFieldInsn(getOpcode, logFieldOwner, "logsize", Type.INT_TYPE.getDescriptor());
+		super.visitInsn(IADD);
+		super.visitInsn(DUP);
+		super.visitFieldInsn(PUTSTATIC, logFieldOwner, "logsize", Type.INT_TYPE.getDescriptor());
+
+		super.visitLdcInsn(Constants.MAX_LOG_SIZE);
+		// super.visitInsn(ISUB);
+		super.visitJumpInsn(IF_ICMPLE, endLbl);
+		// super.ifCmp(Type.INT_TYPE, Opcodes.IFGE, endLbl);
+		// super.visitVarInsn(ALOAD, monitorIndx);
+		// super.monitorExit();
+		if (logFieldOwner.equals(Type.getInternalName(SerializableLog.class)))
+			super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(WallaceExportRunner.class), "_exportSerializable", "()V");
+		else
 			super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(WallaceExportRunner.class), "_export", "()V");
-
-			visitLabel(endLbl);
-			super.visitLocalVariable(logFieldName + "_monitor", "Ljava/lang/Object;", null, monitorStart, monitorEndLabel, monitorIndx);
-//		}
+		// super.visitVarInsn(ALOAD, monitorIndx);
+		// super.monitorEnter();
+		super.visitFieldInsn(getOpcode, logFieldOwner, "logsize", Type.INT_TYPE.getDescriptor());
+		super.visitLdcInsn(Constants.VERY_MAX_LOG_SIZE);
+		super.visitJumpInsn(IF_ICMPLE, endLbl);
+
+		// println("GOing to wait for " + logFieldOwner);
+		// super.visitLabel(tryStart);
+
+		super.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(Log.class), "lock", "Ljava/lang/Object;");
+		super.visitLdcInsn(500L);
+		super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "wait", "(J)V");
+
+		// super.visitLabel(tryEnd);
+
+		// super.visitJumpInsn(GOTO, endLbl);
+		// super.visitLabel(handlerStart);
+		// int n = newLocal(Type.getType(InterruptedException.class));
+		// super.visitVarInsn(ASTORE, n);
+		// super.visitInsn(POP);
+		visitLabel(endLbl);
+//		super.visitVarInsn(ALOAD, monitorIndx);
+//		super.monitorExit();
+		super.visitFieldInsn(GETSTATIC, Type.getInternalName(Log.class), "logLock", Type.getDescriptor(Lock.class));
+		super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "unlock", "()V");
+		// super.visitLocalVariable(logFieldName + "_monitor",
+		// "Ljava/lang/Object;", null, monitorStart, monitorEndLabel,
+		// monitorIndx);
+		// }

 	}

-	protected void onMethodEnter() {
-		// TODO Auto-generated method stub
-
-	}

 }
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldClassVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldClassVisitor.java
deleted file mode 100644
index 8982a64..0000000
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldClassVisitor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package edu.columbia.cs.psl.invivo.record.visitor;
-
-import java.util.HashMap;
-
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.commons.JSRInlinerAdapter;
-import org.objectweb.asm.tree.FieldNode;
-
-import edu.columbia.cs.psl.invivo.record.Constants;
-import edu.columbia.cs.psl.invivo.record.Instrumenter;
-import edu.columbia.cs.psl.invivo.record.struct.FieldExpression;
-
-public class MutatingFieldClassVisitor extends ClassVisitor {
-
-	public MutatingFieldClassVisitor(int api, ClassVisitor cv) {
-		super(api, cv);
-	}
-
-	private String className;
-
-	@Override
-	public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-		// TODO Auto-generated method stub
-		if(interfaces == null)
-			interfaces = new String[]{"java/lang/Cloneable"};
-		else
-		{
-			//Add cloneable to the list of interfaces if it's not already there
-		}
-		super.visit(version, access, name, signature, superName, interfaces);
-		className = name;
-	}
-
-	@Override
-	public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-		MethodVisitor smv = super.visitMethod(access, name, desc, signature, exceptions);
-		JSRInlinerAdapter  mv = new JSRInlinerAdapter(smv, access, name, desc, signature, exceptions);
-		if(name.equals("_copy") || name.equals("_setFieldsOn")) //FIXME this is a bad hack
-			return mv;
-		if (Instrumenter.getAnnotatedMethod(className, name, desc).isMutatesFieldsDirectly()) {
-			for (FieldExpression f : Instrumenter.getAnnotatedMethod(className, name, desc).getPutFieldInsns()) {
-//				System.out.println("\t" + f.getName());
-//				System.out.println("\t\t" + f.getParent());
-//				if(f.getParent() != null && f.getParent().getOpcode() == Opcodes.ALOAD && ((VarInsnNode) ((SimpleExpression) f.getParent()).getInsn()) == null )
-//				{
-//					System.out.println(f);
-//				}
-
-				if(f.getOwner().equals(className) && f.getOpcode() != Opcodes.PUTSTATIC)
-//				if (f.getParent() != null && f.getParent().getOpcode() == Opcodes.ALOAD && ((VarInsnNode) ((SimpleExpression) f.getParent()).getInsn()).var == 0)
-				{
-					putExpressions.put(f.getName(), f);
-				}
-			}
-		}
-		if (Instrumenter.getAnnotatedMethod(className, name, desc).isMutatesFields() || name.startsWith("_copy"))
-			return new MutatingFieldMethodVisitor(access, mv, access, name, desc, className);
-		else
-			return mv;
-	}
-
-	private HashMap<String, FieldExpression> putExpressions = new HashMap<String, FieldExpression>();
-
-	@Override
-	public void visitEnd() {
-		for (FieldExpression f : putExpressions.values()) {
-
-			FieldNode fn = new FieldNode(Opcodes.ASM4, Opcodes.ACC_PUBLIC,
-					Constants.BEEN_CLONED_PREFIX + f.getName(),
-					Type.BOOLEAN_TYPE.getDescriptor(), null, null);
-			fn.accept(cv);
-
-			FieldNode fn2 = new FieldNode(Opcodes.ASM4, Opcodes.ACC_PUBLIC,
-					Constants.PREV_VALUE_PREFIX + f.getName(),
-					f.getDesc(), null, null);
-
-			fn2.accept(cv);
-		}
-
-		super.visitEnd();
-	}
-}
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldMethodVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldMethodVisitor.java
deleted file mode 100644
index 0011fc8..0000000
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/MutatingFieldMethodVisitor.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package edu.columbia.cs.psl.invivo.record.visitor;
-
-import java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.HashSet;
-
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import edu.columbia.cs.psl.invivo.record.Constants;
-import edu.columbia.cs.psl.invivo.record.Instrumenter;
-import edu.columbia.cs.psl.invivo.record.struct.AnnotatedMethod;
-import edu.columbia.cs.psl.invivo.record.struct.Expression;
-import edu.columbia.cs.psl.invivo.record.struct.FieldExpression;
-import edu.columbia.cs.psl.invivo.record.struct.MethodExpression;
-
-public class MutatingFieldMethodVisitor extends CloningAdviceAdapter {
-	// private class FullFieldReference{
-	// private FullFieldReference parent;
-	// private FullFieldReference child;
-	// private Metho
-	// }
-	private ArrayList<FieldExpression> mutatedFieldExpressions = new ArrayList<FieldExpression>();
-	private HashSet<MethodExpression> methodsWeCallIndirectPut = new HashSet<MethodExpression>();
-	private AnnotatedMethod thisMethod;
-	private String owner;
-	private String name;
-	private int access;
-	protected MutatingFieldMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc, String owner) {
-		super(api, mv, access, name, desc,owner);
-		thisMethod = Instrumenter.getAnnotatedMethod(owner, name, desc);
-		this.owner = owner;
-		this.name = name;
-		this.access = access;
-		mutatedFieldExpressions.addAll(thisMethod.getPutFieldInsns());
-
-	}
-
-	private ArrayList<SimpleEntry<Expression, FieldExpression>> buildMethodsMutable(String parent, MethodExpression method) {
-		for (MethodExpression e : method.getMethod().functionsThatICall) {
-			if (e.getMethod().isMutatesFieldsDirectly()) {
-
-			}
-			if (e.getMethod().isMutatesFields()) {
-
-			}
-		}
-		return null;
-	}
-
-
-	/**
-	 * If this method directly changes fields, store a local variable with the
-	 * original value at time of change
-	 *
-	 */
-	@Override
-	public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-		// TODO Auto-generated method stub
-		super.visitMethodInsn(opcode, owner, name, desc);
-	}
-
-	/**
-	 * When visiting a putfield, we need to log the value (duh)
-	 */
-	@Override
-	public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-//		if (opcode == GETFIELD && desc.length() > 1) // Do this in the case of
-//														// objects only
-//		{
-//			// variablesToClear.put(name,desc);
-//			Label lblbForReadThrough = new Label();
-//			dup();
-//			super.visitFieldInsn(GETFIELD, owner, Constants.BEEN_CLONED_PREFIX + name, Type.BOOLEAN_TYPE.getDescriptor());
-//			visitJumpInsn(IFNE, lblbForReadThrough);
-//
-//			dup();
-//			dup();
-//			super.visitFieldInsn(GETSTATIC, "edu/columbia/cs/psl/invivo/record/CloningUtils", "cloner", "Lcom/rits/cloning/Cloner;");
-//			swap();
-//			super.visitFieldInsn(opcode, owner, name, desc);
-//			invokeVirtual(Type.getType(Cloner.class), Method.getMethod("Object deepClone(Object)"));
-//			checkCast(Type.getType(desc));
-//			super.visitFieldInsn(Opcodes.PUTFIELD, owner, Constants.PREV_VALUE_PREFIX + name, desc);
-//
-//			dup();
-//			visitLdcInsn(true);
-//			super.visitFieldInsn(Opcodes.PUTFIELD, owner, Constants.BEEN_CLONED_PREFIX + name, Type.BOOLEAN_TYPE.getDescriptor());
-//
-//			visitLabel(lblbForReadThrough);
-//
-//			super.visitFieldInsn(opcode, owner, name, desc);
-//		}
-		if(this.name.equals("<init>") || this.name.equals("<clinit>") || (this.access & Opcodes.ACC_STATIC) != 0)
-		{
-			super.visitFieldInsn(opcode, owner, name, desc);
-		}
-		else if (opcode == PUTFIELD && desc.length() == 1 ) // If we are going
-																// to do
-		// a putfield on a primitive do a simple copy
-		{
-			// variablesToClear.put(name,desc);
-//			dup();
-
-			super.visitFieldInsn(opcode, owner, name, desc);
-		} else if (opcode == PUTFIELD && desc.length() > 1 && owner.equals(this.owner)) // Need a copy on a
-		// putfield for objects too
-		{
-//			 variablesToClear.put(name,desc);
-			Label lblbForReadThrough = new Label();
-
-//			swap();
-//			dup();
-
-//			loadThis();
-//			super.visitFieldInsn(GETFIELD, owner, Constants.BEEN_CLONED_PREFIX + name, Type.BOOLEAN_TYPE.getDescriptor());
-//			visitJumpInsn(IFNE, lblbForReadThrough);
-
-//			dup();
-//			dup();
-
-			mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
-			mv.visitLdcInsn("Calling copy");
-			mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
-
-			loadThis();
-			loadThis();
-
-			super.visitFieldInsn(GETFIELD, owner, name, desc);
-			cloneValAtTopOfStack(desc);
-			super.visitFieldInsn(Opcodes.PUTFIELD, owner, Constants.PREV_VALUE_PREFIX + name, desc);
-
-//			dup();
-			loadThis();
-			super.push(true);
-			super.visitFieldInsn(Opcodes.PUTFIELD, owner, Constants.BEEN_CLONED_PREFIX + name, Type.BOOLEAN_TYPE.getDescriptor());
-
-//			visitLabel(lblbForReadThrough);
-//			swap();
-			super.visitFieldInsn(opcode, owner, name, desc);
-
-		} else
-			super.visitFieldInsn(opcode, owner, name, desc);
-
-//		super.visitFieldInsn(opcode, owner, name, desc);
-	}
-}
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingClassVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingClassVisitor.java
index 17f442d..4f82504 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingClassVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingClassVisitor.java
@@ -7,6 +7,7 @@ import java.util.HashSet;

 import org.apache.log4j.Logger;
 import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
@@ -55,7 +56,7 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 			LocalVariablesSorter sorter  = new LocalVariablesSorter(acc, desc, mv);
 			// CheckMethodAdapter cmv = new CheckMethodAdapter(mv);

-			NonDeterministicLoggingMethodVisitor cloningMV = new NonDeterministicLoggingMethodVisitor(Opcodes.ASM4, sorter, acc, name, desc, className, isFirstConstructor, analyzer);
+			NonDeterministicLoggingMethodVisitor cloningMV = new NonDeterministicLoggingMethodVisitor(Opcodes.ASM4, sorter, acc, name, desc, className, isFirstConstructor, analyzer, sorter);
 			if (name.equals("<init>"))
 				isFirstConstructor = false;
 			cloningMV.setClassVisitor(this);
@@ -98,14 +99,15 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 				captureDesc += ")" + Type.getReturnType(mi.desc).getDescriptor();
 			}
 			MethodVisitor mv = super.visitMethod(opcode, mc.getCapturePrefix() + "_capture", captureDesc, null, null);
-			CloningAdviceAdapter caa = new CloningAdviceAdapter(Opcodes.ASM4, mv, opcode, mc.getCapturePrefix() + "_capture", captureDesc, className);
+			LocalVariablesSorter lvs = new LocalVariablesSorter(opcode, captureDesc, mv);
+			CloningAdviceAdapter caa = new CloningAdviceAdapter(Opcodes.ASM4, lvs, opcode, mc.getCapturePrefix() + "_capture", captureDesc, className,lvs);
 			Type[] args = Type.getArgumentTypes(captureDesc);
 			if(mi.name.equals("<init>"))
 			{
 				for (int i = 0; i < args.length; i++) {
 					caa.loadArg(i);
 				}
-				mv.visitMethodInsn(Opcodes.INVOKESPECIAL, mi.owner, mi.name, mi.desc);
+				caa.visitMethodInsn(Opcodes.INVOKESPECIAL, mi.owner, mi.name, mi.desc);
 				caa.loadArg(0);
 			}
 			else
@@ -115,13 +117,26 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 				for (int i = 0; i < args.length; i++) {
 					caa.loadArg(i);
 				}
-				mv.visitMethodInsn(mi.getOpcode(), mi.owner, mi.name, mi.desc);
+				caa.visitMethodInsn(mi.getOpcode(), mi.owner, mi.name, mi.desc);
 				for (int i = 0; i < args.length; i++) {
 					if (args[i].getSort() == Type.ARRAY) {
+						boolean minimalCopy = (Type.getReturnType(methodDesc).getSort() == Type.INT);
+						if(minimalCopy)
+						{
+							caa.dup();
+							Label isNegative = new Label();
+							Label notNegative = new Label();
+							caa.visitJumpInsn(Opcodes.IFLT, isNegative);
+							caa.dup();
+							caa.visitJumpInsn(Opcodes.GOTO, notNegative);
+							caa.visitLabel(isNegative);
+							caa.visitInsn(ICONST_0);
+							caa.visitLabel(notNegative);
+						}
 						caa.loadArg(i);
 						//- (mi.getOpcode() == Opcodes.INVOKESTATIC ? 0 : 1)
-						caa.logValueAtTopOfStackToArray(Constants.LOG_DUMP_CLASS, "aLog", "[Ljava/lang/Object;",
-								args[i], true, mi.owner+"."+mi.name+"->_"+i+"\t"+args[i].getDescriptor());
+						caa.logValueAtTopOfStackToArray(MethodCall.getLogClassName(args[i]), "aLog", "[Ljava/lang/Object;",
+								args[i], true, mi.owner+"."+mi.name+"->_"+i+"\t"+args[i].getDescriptor()+"\t\t"+className,minimalCopy);
 						if (args[i].getSize() == 1)
 							caa.pop();
 						else
@@ -130,8 +145,8 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 				}
 			}
 			caa.returnValue();
-			mv.visitMaxs(0, 0);
-			mv.visitEnd();
+			caa.visitMaxs(0, 0);
+			caa.visitEnd();
 		}
 	}

diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingMethodVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingMethodVisitor.java
index 0c17c19..94b4e4c 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingMethodVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/record/visitor/NonDeterministicLoggingMethodVisitor.java
@@ -14,6 +14,7 @@ import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.AnalyzerAdapter;
+import org.objectweb.asm.commons.LocalVariablesSorter;
 import org.objectweb.asm.tree.MethodInsnNode;

 import edu.columbia.cs.psl.invivo.record.Constants;
@@ -61,8 +62,8 @@ public class NonDeterministicLoggingMethodVisitor extends CloningAdviceAdapter i
 	private boolean	isFirstConstructor;

 	protected NonDeterministicLoggingMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc, String classDesc,
-			boolean isFirstConstructor, AnalyzerAdapter analyzer) {
-		super(api, mv, access, name, desc,classDesc);
+			boolean isFirstConstructor, AnalyzerAdapter analyzer, LocalVariablesSorter lvs) {
+		super(api, mv, access, name, desc,classDesc, lvs);
 		this.name = name;
 		this.desc = desc;
 		this.classDesc = classDesc;
@@ -82,13 +83,8 @@ public class NonDeterministicLoggingMethodVisitor extends CloningAdviceAdapter i
 	@Override
 	public void visitEnd() {
 //		System.out.println(classDesc + " " + name);
-		try{
 		super.visitEnd();
-		}
-		catch(ArrayIndexOutOfBoundsException ex)
-		{
-			throw new ArrayIndexOutOfBoundsException("Processing maxs on " +classDesc + "."+ name);
-		}
+
 		parent.addFieldMarkup(methodCallsToClear);
 		parent.addCaptureMethodsToGenerate(captureMethodsToGenerate);
 	}
@@ -136,22 +132,22 @@ public class NonDeterministicLoggingMethodVisitor extends CloningAdviceAdapter i
 						captureDesc+=")"+Type.getReturnType(desc).getDescriptor();
 					}
 					mv.visitMethodInsn(invokeOpcode, classDesc, m.getCapturePrefix()+"_capture", captureDesc);
-					logValueAtTopOfStackToArray(Constants.LOG_DUMP_CLASS, m.getLogFieldName(), m.getLogFieldType().getDescriptor(), returnType, true,
-							owner+"."+name + "\t" + desc);
+					logValueAtTopOfStackToArray(m.getLogClassName(), m.getLogFieldName(), m.getLogFieldType().getDescriptor(), returnType, true,
+							owner+"."+name + "\t" + desc+"\t\t"+classDesc+"."+this.name,false);
 				}
 				else
 				{
 					mv.visitMethodInsn(opcode, owner, name, desc);
-					logValueAtTopOfStackToArray(Constants.LOG_DUMP_CLASS, m.getLogFieldName(), m.getLogFieldType().getDescriptor(), returnType, true,
-							owner+"."+name + "\t" + desc);
+					logValueAtTopOfStackToArray(m.getLogClassName(), m.getLogFieldName(), m.getLogFieldType().getDescriptor(), returnType, true,
+							owner+"."+name + "\t" + desc+"\t\t"+classDesc+"."+this.name,false);
 				}
 			}
 			else if(opcode == INVOKESPECIAL && name.equals("<init>") && nonDeterministicMethods.contains(owner + "." + name + ":" + desc) && !(owner.equals(Instrumenter.instrumentedClasses.get(classDesc).superName)
 					&& this.name.equals("<init>"))) {
 				super.visitMethodInsn(opcode, owner, name, desc);
 				if(analyzer.stack != null && analyzer.stack.size() > 0 && analyzer.stack.get(analyzer.stack.size()-1).equals(owner))
-					logValueAtTopOfStackToArray(Constants.LOG_DUMP_CLASS, "aLog", "[Ljava/lang/Object;", Type.getType("L"+owner+";"), true,
-							owner+"."+name + "\t" + desc);
+					logValueAtTopOfStackToArray(MethodCall.getLogClassName(Type.getType("L"+owner+";")), "aLog", "[Ljava/lang/Object;", Type.getType("L"+owner+";"), true,
+							owner+"."+name + "\t" + desc+"\t\t"+classDesc+"."+this.name,false);

 			}
 			else
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayClassVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayClassVisitor.java
index 9f3ee70..c92d038 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayClassVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayClassVisitor.java
@@ -72,70 +72,7 @@ public class NonDeterministicReplayClassVisitor extends ClassVisitor implements
 	@Override
 	public void visitEnd() {
 		super.visitEnd();
-//		for(String logFieldName : captureMethodsToGenerate.keySet())
-//		{
-//			MethodInsnNode mi = captureMethodsToGenerate.get(logFieldName);
-//			String methodDesc = mi.desc;
-//
-//			String captureDesc = mi.desc;
-//			if(mi.getOpcode() != Opcodes.INVOKESTATIC)
-//			{
-//				//Need to put owner of the method on the top of the args list
-//				captureDesc = "(L" +  mi.owner +";";
-//				for(Type t : Type.getArgumentTypes(mi.desc))
-//					captureDesc += t.getDescriptor();
-//				captureDesc+=")"+Type.getReturnType(mi.desc).getDescriptor();
-//			}
-//			MethodVisitor mv = super.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, logFieldName+"_capture", captureDesc, null, null);
-//			CloningAdviceAdapter caa = new CloningAdviceAdapter(Opcodes.ASM4, mv, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,logFieldName+"_capture", captureDesc, className);
-//			Type[] args = Type.getArgumentTypes(captureDesc);
-//			for(int i = 0; i < args.length ; i++)
-//			{
-//				caa.loadArg(i);
-//			}
-//			mv.visitMethodInsn(mi.getOpcode(), mi.owner, mi.name, mi.desc);
-//			for(int i = 0; i< args.length; i++)
-//			{
-//				if(args[i].getSort() == Type.ARRAY)
-//				{
-//					caa.loadArg(i);
-//
-//					//caa.logValueAtTopOfStackToArray(className + Constants.LOG_CLASS_SUFFIX, logFieldName+"_"+(i-(mi.getOpcode() == Opcodes.INVOKESTATIC ? 0 : 1)), "["+args[i].getDescriptor(), args[i], true);
-//
-//					if(args[i].getSize() == 1)
-//						caa.pop();
-//					else
-//						caa.pop2();
-//				}
-//			}
-//			caa.returnValue();
-//			mv.visitMaxs(0, 0);
-//			mv.visitEnd();
-//		}

-		/*{
-			MethodVisitor mv = this.visitMethod(Opcodes.ACC_PUBLIC, Constants.INNER_COPY_METHOD_NAME, "()L"+className+";", null, null);
-			CloningAdviceAdapter cloningAdapter = new CloningAdviceAdapter(Opcodes.ASM4, mv, Opcodes.ACC_PUBLIC, Constants.INNER_COPY_METHOD_NAME, "()L"+className+";", className);
-			//cloningAdapter.generateCopyMethod();
-			mv.visitMaxs(0, 0);
-			cloningAdapter.returnValue();
-			mv.visitEnd();
-		}
-		{
-			MethodVisitor mv = this.visitMethod(Opcodes.ACC_PUBLIC, Constants.OUTER_COPY_METHOD_NAME, "()L"+className+";", null, null);
-			CloningAdviceAdapter cloningAdapter = new CloningAdviceAdapter(Opcodes.ASM4, mv, Opcodes.ACC_PUBLIC, Constants.OUTER_COPY_METHOD_NAME, "()L"+className+";", className);
-			//cloningAdapter.generateOuterCopyMethod();
-			mv.visitMaxs(0, 0);
-			cloningAdapter.returnValue();
-			mv.visitEnd();
-		}
-		{
-			MethodVisitor mv = this.visitMethod(Opcodes.ACC_PUBLIC, Constants.SET_FIELDS_METHOD_NAME, "(L"+className+";)L"+className+";", null, null);
-			CloningAdviceAdapter cloningAdapter = new CloningAdviceAdapter(Opcodes.ASM4, mv, Opcodes.ACC_PUBLIC, Constants.SET_FIELDS_METHOD_NAME, "(L"+className+";)L"+className+";", className);
-			mv.visitMaxs(0, 0);
-			cloningAdapter.returnValue();
-			mv.visitEnd();
-		}*/
 	}
 	public String getClassName() {
 		return className;
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayMethodVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayMethodVisitor.java
index 7e1b825..11401fb 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayMethodVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/NonDeterministicReplayMethodVisitor.java
@@ -19,7 +19,9 @@ import org.objectweb.asm.tree.MethodInsnNode;

 import edu.columbia.cs.psl.invivo.record.CloningUtils;
 import edu.columbia.cs.psl.invivo.record.Constants;
+import edu.columbia.cs.psl.invivo.record.ExportedLog;
 import edu.columbia.cs.psl.invivo.record.Instrumenter;
+import edu.columbia.cs.psl.invivo.record.Log;
 import edu.columbia.cs.psl.invivo.record.MethodCall;
 import edu.columbia.cs.psl.invivo.record.visitor.CloningAdviceAdapter;

@@ -57,7 +59,7 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im

 	protected NonDeterministicReplayMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc, String classDesc,
 			boolean isFirstConstructor) {
-		super(api, mv, access, name, desc,classDesc);
+		super(api, mv, access, name, desc,classDesc, null);
 		this.name = name;
 		this.desc = desc;
 		this.classDesc = classDesc;
@@ -72,10 +74,7 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 		this.parent = coaClassVisitor;
 	}

-	@Override
-	protected void onMethodEnter() {
-		super.onMethodEnter();
-	}
+

 	@Override
 	public void visitEnd() {
@@ -91,7 +90,47 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 		super.visitLineNumber(line, start);
 		lineNumber = line;
 	}
-
+	private void loadReplayIndex(String className, String fieldName)
+	{
+		/*
+		  GETSTATIC edu/columbia/cs/psl/invivo/record/ExportedLog.aLog_replayIndex : Ljava/util/HashMap;
+		    INVOKESTATIC java/lang/Thread.currentThread()Ljava/lang/Thread;
+		    INVOKEVIRTUAL java/lang/Thread.getName()Ljava/lang/String;
+		    INVOKEVIRTUAL java/util/HashMap.containsKey(Ljava/lang/Object;)Z
+		    IFNE L1
+		   L2
+		    LINENUMBER 45 L2
+		    GETSTATIC edu/columbia/cs/psl/invivo/record/ExportedLog.aLog_replayIndex : Ljava/util/HashMap;
+		    INVOKESTATIC java/lang/Thread.currentThread()Ljava/lang/Thread;
+		    INVOKEVIRTUAL java/lang/Thread.getName()Ljava/lang/String;
+		    ICONST_0
+		    INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
+		    INVOKEVIRTUAL java/util/HashMap.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+		    POP
+		   L1
+		    LINENUMBER 46 L1
+		   FRAME SAME
+		    GETSTATIC edu/columbia/cs/psl/invivo/record/ExportedLog.aLog_replayIndex : Ljava/util/HashMap;
+		    INVOKESTATIC java/lang/Thread.currentThread()Ljava/lang/Thread;
+		    INVOKEVIRTUAL java/lang/Thread.getName()Ljava/lang/String;
+		    INVOKEVIRTUAL java/util/HashMap.get(Ljava/lang/Object;)Ljava/lang/Object;
+		    CHECKCAST java/lang/Integer
+		    INVOKEVIRTUAL java/lang/Integer.intValue()I
+		 */
+		super.visitFieldInsn(GETSTATIC, Type.getInternalName(ExportedLog.class), fieldName+"_replayIndex", "Ljava/util/HashMap;");
+		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
+		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
+		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "containsKey", "(Ljava/lang/Object;)Z");
+		Label exists = new Label();
+		super.visitFieldInsn(GETSTATIC, Type.getInternalName(ExportedLog.class), fieldName+"_replayIndex", "Ljava/util/HashMap;");
+		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
+		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
+		super.visitInsn(ICONST_0);
+		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Integer.class), "valueOf", "(I)java/lang/Integer;");
+		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+		super.visitJumpInsn(Opcodes.IFNE, exists);
+	}
 	private HashMap<String, MethodInsnNode> captureMethodsToGenerate = new HashMap<String, MethodInsnNode>();
 	@Override
 	public void visitMethodInsn(int opcode, String owner, String name, String desc) {
@@ -125,10 +164,8 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 				Label startOfPlayBack = new Label();


-				//Also acquire a read lock for the export lock
-//				super.visitFieldInsn(GETSTATIC, Type.getInternalName(CloningUtils.class), "exportLock", Type.getDescriptor(ReadWriteLock.class));
-//				super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(ReadWriteLock.class), "readLock", "()Ljava/util/concurrent/locks/Lock;");
-//				super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "lock", "()V");
+				super.visitFieldInsn(GETSTATIC, Type.getInternalName(Log.class), "logLock", Type.getDescriptor(Lock.class));
+				super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "lock", "()V");

 				logger.debug("Adding field in MV to list " + m.getLogFieldName());
 				methodCallsToClear.add(m);
@@ -148,27 +185,27 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 							 * stack (grows down):
 							 * dest (fill not incremented yet)
 							 */
-							mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS,
+							String replayClassName = MethodCall.getReplayClassName(t);
+							mv.visitFieldInsn(GETSTATIC, replayClassName,
 									MethodCall.getLogFieldName(t),
 									MethodCall.getLogFieldType(t).getDescriptor());
-							mv.visitFieldInsn(GETSTATIC,Constants.LOG_REPLAY_CLASS,
+							mv.visitFieldInsn(GETSTATIC,replayClassName,
 									MethodCall.getLogFieldName(t)+"_replayIndex",
 									"I");
 							mv.visitInsn(DUP);
-							mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS, MethodCall.getLogFieldName(t)+"_fill", "I");
+							mv.visitFieldInsn(GETSTATIC, replayClassName, MethodCall.getLogFieldName(t)+"_fill", "I");
 							Label fallThrough = new Label();


 							mv.visitJumpInsn(Opcodes.IF_ICMPNE, fallThrough);
 							mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReplayRunner.class), "loadNextLog", "()V");
 							pop();
-							mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS,
+							mv.visitFieldInsn(GETSTATIC, replayClassName,
 									MethodCall.getLogFieldName(t) +"_replayIndex",
 									"I");
 							visitLabel(fallThrough);

 							arrayLoad(t);
-//							mv.visitTypeInsn(Opcodes.CHECKCAST, t.getInternalName());

 							/*
 							 * stack (grows down):
@@ -204,16 +241,16 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 							 * 0
 							 */

-							mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS,
+							mv.visitFieldInsn(GETSTATIC, replayClassName,
 									MethodCall.getLogFieldName(t),
 									MethodCall.getLogFieldType(t).getDescriptor());
-							mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS,
+							mv.visitFieldInsn(GETSTATIC, replayClassName,
 									MethodCall.getLogFieldName(t)+"_replayIndex",
 									"I");
 							mv.visitInsn(DUP);
 							mv.visitInsn(ICONST_1);
 							mv.visitInsn(IADD);
-							mv.visitFieldInsn(PUTSTATIC, Constants.LOG_REPLAY_CLASS,
+							mv.visitFieldInsn(PUTSTATIC, replayClassName,
 									MethodCall.getLogFieldName(t) +"_replayIndex",
 									"I");
 							arrayLoad(t);
@@ -267,17 +304,17 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 				if (returnType.getSort() == Type.VOID)
 					mv.visitInsn(NOP);
 				else {
-					mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS,
+					mv.visitFieldInsn(GETSTATIC, m.getReplayClassName(),
 							m.getLogFieldName(),
 							m.getLogFieldType().getDescriptor());
-					mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS, m.getLogFieldName()+"_replayIndex", "I");
+					mv.visitFieldInsn(GETSTATIC, m.getReplayClassName(), m.getLogFieldName()+"_replayIndex", "I");
 					mv.visitInsn(DUP);
 					Label fallThrough = new Label();
-					mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS, m.getLogFieldName()+"_fill", "I");
+					mv.visitFieldInsn(GETSTATIC, m.getReplayClassName(), m.getLogFieldName()+"_fill", "I");
 					mv.visitJumpInsn(Opcodes.IF_ICMPNE, fallThrough);
 					mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReplayRunner.class), "loadNextLog", "()V");
 					mv.visitInsn(POP);
-					mv.visitFieldInsn(GETSTATIC, Constants.LOG_REPLAY_CLASS,
+					mv.visitFieldInsn(GETSTATIC, m.getReplayClassName(),
 							m.getLogFieldName() +"_replayIndex",
 							"I");

@@ -285,14 +322,12 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 					mv.visitInsn(DUP);
 					mv.visitInsn(ICONST_1);
 					mv.visitInsn(IADD);
-					mv.visitFieldInsn(PUTSTATIC, Constants.LOG_REPLAY_CLASS, m.getLogFieldName()+"_replayIndex", "I");
+					mv.visitFieldInsn(PUTSTATIC, m.getReplayClassName(), m.getLogFieldName()+"_replayIndex", "I");
 					arrayLoad(m.getReturnType());
 				}
-				//Release the export lock
-//				super.visitFieldInsn(GETSTATIC, Type.getInternalName(CloningUtils.class), "exportLock", Type.getDescriptor(ReadWriteLock.class));
-//				super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(ReadWriteLock.class), "readLock", "()Ljava/util/concurrent/locks/Lock;");
-//				super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "unlock", "()V");
-//
+				//Unlock
+				super.visitFieldInsn(GETSTATIC, Type.getInternalName(Log.class), "logLock", Type.getDescriptor(Lock.class));
+				super.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Lock.class), "unlock", "()V");

 			} else {
 				super.visitMethodInsn(opcode, owner, name, desc);
diff --git a/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/ReplayRunner.java b/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/ReplayRunner.java
index 5facba1..ae3b1b2 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/ReplayRunner.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/invivo/replay/ReplayRunner.java
@@ -1,7 +1,9 @@
 package edu.columbia.cs.psl.invivo.replay;

 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileWriter;
+import java.io.ObjectInputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
@@ -9,39 +11,50 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;

+import org.objectweb.asm.Type;
+
 import com.thoughtworks.xstream.XStream;

 import edu.columbia.cs.psl.invivo.record.CloningUtils;
 import edu.columbia.cs.psl.invivo.record.Constants;
 import edu.columbia.cs.psl.invivo.record.ExportedLog;
+import edu.columbia.cs.psl.invivo.record.ExportedSerializableLog;
+import edu.columbia.cs.psl.invivo.record.Log;
 import edu.columbia.cs.psl.invivo.record.xstream.StaticReflectionProvider;

 public class ReplayRunner {
-	public static String[]	logFiles;
-	private static int		nextLog	= 0;
+	public static String[] logFiles;
+	public static String[] serializableLogFiles;
+
+	private static int nextLog = 0;
+	private static int nextSerializableLog = 0;

-	public static void loadNextLog() {
+	public static void loadNextLog(String logClass) {
 		try {
-			CloningUtils.exportLock.writeLock().lock();
-			_loadNextLog();
-			CloningUtils.exportLock.writeLock().unlock();
+			Log.logLock.lock();
+			_loadNextLog(logClass);
+			Log.logLock.unlock();
 		} catch (Exception exi) {
 			exi.printStackTrace();
 		}
 	}

-	private static void _loadNextLog() {
+	private static void _loadNextLog(String logClass) {
 		try {
-			XStream xstream = new XStream(new StaticReflectionProvider());
-			Object o = xstream.fromXML(new File(logFiles[nextLog]));
-//			ExportedLog.aLog_replayIndex = 1;
-//			ExportedLog.iLog_replayIndex = 1;
-			nextLog++;
+			if (logClass.contains("Serializable")) {
+				ObjectInputStream is = new ObjectInputStream(new FileInputStream(serializableLogFiles[nextSerializableLog]));
+				ExportedSerializableLog el = (ExportedSerializableLog) is.readObject();
+				nextSerializableLog++;
+			} else {
+				XStream xstream = new XStream(new StaticReflectionProvider());
+				Object o = xstream.fromXML(new File(logFiles[nextLog]));
+				nextLog++;
+			}
 		} catch (Exception exi) {
 			exi.printStackTrace();
 		}
 	}
-
+
 	public static void main(String[] args) {
 		if (args.length < 2) {
 			System.err.println("Usage: ReplayRunner <mainClass> log [log2...logN] class_args [arg1...argM]");
@@ -49,19 +62,29 @@ public class ReplayRunner {
 		}
 		String mainClass = args[0];
 		logFiles = new String[args.length - 1];
+		serializableLogFiles = new String[args.length - 1];
 		int class_args = args.length;
+		int nLogs = 0;
+		int nSerializableLogs = 0;
+
 		for (int i = 1; i < args.length; i++) {
 			if (!args[i].equals("class_args"))
-				logFiles[i - 1] = args[i];
+				if (args[i].contains("_serializable_")) {
+					serializableLogFiles[nSerializableLogs] = args[i];
+					nSerializableLogs++;
+				} else {
+					logFiles[nLogs] = args[i];
+					nLogs++;
+				}
 			else {
 				class_args = i + 1;
 				break;
 			}
 		}
-
-		System.out.println("Available logs: " + Arrays.deepToString(logFiles));
-		_loadNextLog();

+		System.out.println("Available logs: " + Arrays.deepToString(logFiles));
+		_loadNextLog(Type.getDescriptor(ExportedLog.class));
+		_loadNextLog(Type.getDescriptor(ExportedSerializableLog.class));
 		Class<?> toRun;
 		try {
 			toRun = Class.forName(mainClass);
@@ -69,7 +92,7 @@ public class ReplayRunner {
 			String[] params = new String[args.length - class_args];
 			if (class_args < args.length)
 				System.arraycopy(args, class_args, params, 0, params.length);
-		    meth.invoke(null, new Object[]{ params });
+			meth.invoke(null, new Object[] { params });
 		} catch (ClassNotFoundException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();