Callback logging

Jonathan Bell [2012-08-15 20:51:23]
Callback logging
Filename
native-detector/native-methods-to-ignore.txt
testcase-generation-tester/.classpath
testcase-generation/nondeterministic-methods.txt
testcase-generation/src/edu/columbia/cs/psl/wallace/ExportedLog.java
testcase-generation/src/edu/columbia/cs/psl/wallace/Instrumenter.java
testcase-generation/src/edu/columbia/cs/psl/wallace/MethodCall.java
testcase-generation/src/edu/columbia/cs/psl/wallace/SerializableLog.java
testcase-generation/src/edu/columbia/cs/psl/wallace/WallaceExportRunner.java
testcase-generation/src/edu/columbia/cs/psl/wallace/analysis/MutabilityAnalyzer.java
testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayClassVisitor.java
testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayMethodVisitor.java
testcase-generation/src/edu/columbia/cs/psl/wallace/replay/ReplayRunner.java
testcase-generation/src/edu/columbia/cs/psl/wallace/replay/Replayer.java
testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/CloningAdviceAdapter.java
testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/NonDeterministicLoggingClassVisitor.java
testcase-generation/src/edu/columbia/cs/psl/wallace/xstream/StaticReflectionProvider.java
diff --git a/native-detector/native-methods-to-ignore.txt b/native-detector/native-methods-to-ignore.txt
index de96b4c..bc2faf2 100644
--- a/native-detector/native-methods-to-ignore.txt
+++ b/native-detector/native-methods-to-ignore.txt
@@ -5546,3 +5546,5 @@ java/awt/Rectangle.setSize:(Ljava/awt/Dimension;)V
 java/awt/Rectangle.toString:()Ljava/lang/String;
 java/awt/Rectangle.translate:(II)V
 java/awt/Rectangle.union:(Ljava/awt/Rectangle;)Ljava/awt/Rectangle;
+java/lang/Throwable.printStackTrace:(Ljava/io/PrintStream;)V
+java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
\ No newline at end of file
diff --git a/testcase-generation-tester/.classpath b/testcase-generation-tester/.classpath
index 59e9444..8b2a61d 100644
--- a/testcase-generation-tester/.classpath
+++ b/testcase-generation-tester/.classpath
@@ -9,10 +9,5 @@
 	<classpathentry kind="lib" path="lib/kxml2-2.3.0.jar"/>
 	<classpathentry kind="lib" path="lib/xstream-1.4.2.jar"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/test case generation"/>
-	<classpathentry kind="lib" path="/home/nikhil/in-vivo/testcase-generation-tester/lib/jetty-http-7.5.4.v20111024.jar"/>
-	<classpathentry kind="lib" path="/home/nikhil/in-vivo/testcase-generation-tester/lib/jetty-io-7.5.4.v20111024.jar"/>
-	<classpathentry kind="lib" path="/home/nikhil/in-vivo/testcase-generation-tester/lib/jetty-util-7.5.4.v20111024.jar"/>
-	<classpathentry kind="lib" path="/home/nikhil/in-vivo/testcase-generation-tester/lib/jetty-server-7.5.4.v20111024.jar"/>
-	<classpathentry kind="lib" path="/home/nikhil/in-vivo/testcase-generation-tester/lib/jetty-servlet-7.5.4.v20111024.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/testcase-generation/nondeterministic-methods.txt b/testcase-generation/nondeterministic-methods.txt
index ab18e01..d2c068f 100644
--- a/testcase-generation/nondeterministic-methods.txt
+++ b/testcase-generation/nondeterministic-methods.txt
@@ -3967,7 +3967,6 @@ com/sun/tools/corba/se/idl/ForwardEntry.clone:()Ljava/lang/Object;
 com/sun/org/apache/xml/internal/serializer/Encodings.convertJava2MimeEncoding:(Ljava/lang/String;)Ljava/lang/String;
 sun/security/provider/X509Factory.addToCache:(Lsun/security/util/Cache;[BLjava/lang/Object;)V
 javax/swing/plaf/basic/BasicProgressBarUI.getAnimationIndex:()I
-java/lang/Throwable.printStackTrace:(Ljava/io/PrintStream;)V
 com/sun/xml/internal/bind/v2/model/impl/ModelBuilder.getRegistry:(Ljava/lang/String;)Lcom/sun/xml/internal/bind/v2/model/core/RegistryInfo;
 com/sun/xml/internal/dtdparser/Resolver.resolveEntity:(Ljava/lang/String;Ljava/lang/String;)Lorg/xml/sax/InputSource;
 com/sun/xml/internal/rngom/digested/DChoicePattern.isNullable:()Z
@@ -21725,7 +21724,6 @@ org/jcp/xml/dsig/internal/dom/DOMXMLSignature.marshal:(Lorg/w3c/dom/Node;Lorg/w3
 java/util/jar/JarEntry.<init>:(Ljava/util/jar/JarEntry;)V
 sun/font/ExtendedTextLabel.getCharX:(I)F
 com/sun/corba/se/impl/logging/ORBUtilSystemException.adapterIdNotAvailable:(Lorg/omg/CORBA/CompletionStatus;Ljava/lang/Throwable;)Lorg/omg/CORBA/BAD_OPERATION;
-java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
 com/sun/java/swing/plaf/motif/MotifDesktopPaneUI$MotifDesktopManager.beginResizingFrame:(Ljavax/swing/JComponent;I)V
 com/sun/rowset/internal/SyncResolverImpl.readObject:(Ljava/io/ObjectInputStream;)V
 com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3.<init>:()V
@@ -61348,7 +61346,6 @@ com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/ForkingFilter.endDocument:(
 sun/security/provider/certpath/ConstraintsChecker.getSupportedExtensions:()Ljava/util/Set;
 javax/management/ObjectName.isPropertyListPattern:()Z
 javax/swing/GroupLayout$Group.calculatePreferredSize:(I)I
-javax/swing/JPanel.<init>:()V
 com/sun/tools/javac/jvm/Code.emit4:(I)V
 sun/net/www/protocol/http/InMemoryCookieStore.getInternal1:(Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Z)V
 sun/print/UnixPrintJob.access$900:(Lsun/print/UnixPrintJob;)Ljava/lang/String;
@@ -88991,7 +88988,6 @@ javax/xml/bind/DatatypeConverter.printDouble:(D)Ljava/lang/String;
 com/sun/corba/se/spi/activation/ORBidHelper.extract:(Lorg/omg/CORBA/Any;)Ljava/lang/String;
 com/sun/tools/jdi/SDE.fileTableIndex:(II)I
 com/sun/corba/se/impl/encoding/TypeCodeOutputStream.<init>:(Lcom/sun/corba/se/spi/orb/ORB;)V
-javax/swing/JFrame.<init>:()V
 com/sun/org/apache/xerces/internal/impl/dtd/models/DFAContentModel.calcFollowList:(Lcom/sun/org/apache/xerces/internal/impl/dtd/models/CMNode;)V
 com/sun/tools/jdwpgen/SelectNode.constrainComponent:(Lcom/sun/tools/jdwpgen/Context;Lcom/sun/tools/jdwpgen/Node;)V
 sun/tools/tree/CommaExpression.codeLoad:(Lsun/tools/java/Environment;Lsun/tools/tree/Context;Lsun/tools/asm/Assembler;)V
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/ExportedLog.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/ExportedLog.java
index b6945cc..0667cff 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/ExportedLog.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/ExportedLog.java
@@ -7,10 +7,12 @@ public class ExportedLog {
 	public static String[] aLog_owners = new String[Constants.DEFAULT_LOG_SIZE];

 	public static int aLog_fill;
+	public static int globalReplayIndex = 0;
 	public static HashMap<String, Integer> aLog_replayIndex = new HashMap<String, Integer>();
 	public static void clearLog() {
 		aLog = new Object[Constants.DEFAULT_LOG_SIZE];
 		aLog_owners =  new String[Constants.DEFAULT_LOG_SIZE];
 		aLog_fill = 0;
+		globalReplayIndex = 0;
 	}
 }
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/Instrumenter.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/Instrumenter.java
index 61c8c72..d511b6f 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/Instrumenter.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/Instrumenter.java
@@ -105,6 +105,7 @@ public class Instrumenter {
 			return out;
 		} catch (Exception ex) {
 			logger.error("Exception processing class: " + lastInstrumentedClass, ex);
+			ex.printStackTrace();
 			return null;
 		}
 	}
@@ -177,6 +178,7 @@ public class Instrumenter {
 			try {
 					FileOutputStream fos = new FileOutputStream(outputDir.getPath() + File.separator + name);
 					ByteArrayOutputStream bos = new ByteArrayOutputStream();
+					lastInstrumentedClass = outputDir.getPath() + File.separator + name;
 					bos.write(instrumentClass(is));
 					bos.writeTo(fos);
 					fos.close();
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/MethodCall.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/MethodCall.java
index 469fdba..93028be 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/MethodCall.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/MethodCall.java
@@ -2,6 +2,8 @@ package edu.columbia.cs.psl.wallace;

 import java.util.HashSet;

+import javax.swing.JFrame;
+
 import org.objectweb.asm.Type;

 public class MethodCall {
@@ -18,6 +20,8 @@ public class MethodCall {
 	private static HashSet<String> serializableClasses = new HashSet<String>();
 	static{
 		serializableClasses.add(Type.getType(String.class).getInternalName());
+		serializableClasses.add(Type.getType(JFrame.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;
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/SerializableLog.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/SerializableLog.java
index 9c6838c..49d504a 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/SerializableLog.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/SerializableLog.java
@@ -6,7 +6,7 @@ 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];
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/WallaceExportRunner.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/WallaceExportRunner.java
index 81505af..f92dd84 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/WallaceExportRunner.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/WallaceExportRunner.java
@@ -131,6 +131,7 @@ public class WallaceExportRunner extends Thread {

 	public static void export() {
 		shouldExport = 0;
+		System.out.println("Export");
 		try {
 			XStream xstream = new XStream(new StaticReflectionProvider());
 			String xml = "";
@@ -167,6 +168,7 @@ public class WallaceExportRunner extends Thread {
 	public static void exportSerializable() {
 		shouldExportSerializable = 0;
 		try {
+			System.out.println("Export_s");

 			Log.logLock.lock();
 			{
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/analysis/MutabilityAnalyzer.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/analysis/MutabilityAnalyzer.java
index a2097af..a3a3a04 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/analysis/MutabilityAnalyzer.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/analysis/MutabilityAnalyzer.java
@@ -152,6 +152,7 @@ public class MutabilityAnalyzer implements Opcodes {
 		ret.name = cn.name;
 		ret.fields = cn.fields;
 		ret.superName = cn.superName;
+		ret.interfaces = cn.interfaces;
 		return ret;
 	}

diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayClassVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayClassVisitor.java
index 6140496..b59ba25 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayClassVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayClassVisitor.java
@@ -11,13 +11,16 @@ import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.AnalyzerAdapter;
 import org.objectweb.asm.commons.JSRInlinerAdapter;
+import org.objectweb.asm.tree.ClassNode;
 import org.objectweb.asm.tree.FieldNode;
 import org.objectweb.asm.tree.MethodInsnNode;
 import org.objectweb.asm.util.CheckMethodAdapter;

 import edu.columbia.cs.psl.wallace.Constants;
+import edu.columbia.cs.psl.wallace.Instrumenter;
 import edu.columbia.cs.psl.wallace.MethodCall;
 import edu.columbia.cs.psl.wallace.visitor.CloningAdviceAdapter;
+import edu.columbia.cs.psl.wallace.visitor.NonDeterministicLoggingClassVisitor;

 public class NonDeterministicReplayClassVisitor extends ClassVisitor implements Opcodes{

@@ -47,15 +50,17 @@ public class NonDeterministicReplayClassVisitor extends ClassVisitor implements
 		{

 			MethodVisitor smv = cv.visitMethod(acc, name, desc, signature, exceptions);
-			JSRInlinerAdapter mv = new JSRInlinerAdapter(smv, acc, name, desc, signature, exceptions);

-			AnalyzerAdapter analyzer = new AnalyzerAdapter(className, acc, name, desc, mv);
-			CheckMethodAdapter cm = new CheckMethodAdapter(analyzer);
-			NonDeterministicReplayMethodVisitor cloningMV = new NonDeterministicReplayMethodVisitor(Opcodes.ASM4, cm, acc, name, desc,className,isFirstConstructor, analyzer);
+			AnalyzerAdapter analyzer = new AnalyzerAdapter(className, acc, name, desc, smv);
+//CheckMethodAdapter cm = new CheckMethodAdapter(analyzer);
+			NonDeterministicReplayMethodVisitor cloningMV = new NonDeterministicReplayMethodVisitor(Opcodes.ASM4, analyzer, acc, name, desc,className,isFirstConstructor, analyzer,
+					classIsCallback(className) && name.equals("<init>"));
 			if(name.equals("<init>"))
 				isFirstConstructor = false;
 			cloningMV.setClassVisitor(this);
-			return cloningMV;
+			JSRInlinerAdapter mv = new JSRInlinerAdapter(cloningMV, acc, name, desc, signature, exceptions);
+
+			return mv;
 		}
 		else
 			return 	cv.visitMethod(acc, name, desc, signature,
@@ -73,6 +78,35 @@ public class NonDeterministicReplayClassVisitor extends ClassVisitor implements
 		//TODO also setup the new method to retrieve the list of replacements for the method
 	}

+	private boolean classIsCallback(String className)
+	{
+		if(NonDeterministicLoggingClassVisitor.callbackClasses.contains(className))
+			return true;
+		if(!Replayer.instrumentedClasses.containsKey(className))
+			return false;
+		ClassNode cn = Replayer.instrumentedClasses.get(className);
+		for(Object s : cn.interfaces)
+		{
+			if(NonDeterministicLoggingClassVisitor.callbackClasses.contains(((String)s)))
+				return true;
+		}
+		return classIsCallback(cn.superName);
+	}
+	public static boolean methodIsCallback(String className, String name, String desc)
+	{
+		String key = "."+name +":"+desc;
+		if(NonDeterministicLoggingClassVisitor.callbackMethods.contains(className + key))
+			return true;
+		if(!Replayer.instrumentedClasses.containsKey(className))
+			return false;
+		ClassNode cn = Replayer.instrumentedClasses.get(className);
+		for(Object s : cn.interfaces)
+		{
+			if(NonDeterministicLoggingClassVisitor.callbackMethods.contains(((String)s) + key))
+				return true;
+		}
+		return methodIsCallback(cn.superName, name, desc);
+	}
 	@Override
 	public void visitEnd() {
 		super.visitEnd();
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayMethodVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayMethodVisitor.java
index dcbcc0b..343b19b 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayMethodVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/NonDeterministicReplayMethodVisitor.java
@@ -18,6 +18,7 @@ import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.AnalyzerAdapter;
 import org.objectweb.asm.tree.MethodInsnNode;

+import edu.columbia.cs.psl.wallace.CallbackRegistry;
 import edu.columbia.cs.psl.wallace.CloningUtils;
 import edu.columbia.cs.psl.wallace.Constants;
 import edu.columbia.cs.psl.wallace.ExportedLog;
@@ -28,16 +29,17 @@ import edu.columbia.cs.psl.wallace.visitor.CloningAdviceAdapter;
 import edu.columbia.cs.psl.wallace.visitor.NonDeterministicLoggingMethodVisitor;

 public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter implements Constants {
-	private static Logger			logger					= Logger.getLogger(NonDeterministicReplayMethodVisitor.class);
-	private String					name;
-	private String					desc;
-	private String					classDesc;
-	private int						pc;
-	private boolean					isStatic;
-	private boolean					constructor;
-	private boolean					superInitialized;
-
-
+	private static Logger logger = Logger.getLogger(NonDeterministicReplayMethodVisitor.class);
+	private String name;
+	private String desc;
+	private String classDesc;
+	private int pc;
+	private boolean isStatic;
+	private boolean constructor;
+	private boolean superInitialized;
+
+	private boolean isCallbackInit;
+
 	@Override
 	public void visitCode() {
 		super.visitCode();
@@ -45,11 +47,11 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 			superInitialized = true;
 	}

-	private boolean	isFirstConstructor;
-	AnalyzerAdapter	analyzer;
+	private boolean isFirstConstructor;
+	AnalyzerAdapter analyzer;

-	protected NonDeterministicReplayMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc, String classDesc,
-			boolean isFirstConstructor, AnalyzerAdapter analyzer) {
+	protected NonDeterministicReplayMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc, String classDesc, boolean isFirstConstructor, AnalyzerAdapter analyzer,
+			boolean isCallbackInit) {
 		super(api, mv, access, name, desc, classDesc, null);
 		this.name = name;
 		this.desc = desc;
@@ -58,14 +60,17 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 		this.constructor = "<init>".equals(name);
 		this.isFirstConstructor = isFirstConstructor;
 		this.analyzer = analyzer;
+		this.isCallbackInit = isCallbackInit;
 	}

-	private NonDeterministicReplayClassVisitor	parent;
+	private NonDeterministicReplayClassVisitor parent;

 	public void setClassVisitor(NonDeterministicReplayClassVisitor coaClassVisitor) {
 		this.parent = coaClassVisitor;
 	}

+
+
 	@Override
 	public void visitEnd() {
 		super.visitEnd();
@@ -73,7 +78,7 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 		parent.addCaptureMethodsToGenerate(captureMethodsToGenerate);
 	}

-	private int	lineNumber	= 0;
+	private int lineNumber = 0;

 	@Override
 	public void visitLineNumber(int line, Label start) {
@@ -82,90 +87,108 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 	}

 	private void loadReplayIndex(String className, String fieldName) {
-		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
-		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
-		super.visitMethodInsn(INVOKEVIRTUAL, 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.visitJumpInsn(Opcodes.IFNE, exists);
-		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
-		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
-		super.visitInsn(ICONST_0);
-		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Integer.class), "valueOf", "(I)Ljava/lang/Integer;");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-		super.visitInsn(POP);
-		super.visitLabel(exists);
-		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
-		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
-		super.visitTypeInsn(CHECKCAST, "java/lang/Integer");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Integer.class), "intValue", "()I");
-//				super.visitInsn(ICONST_0);
+		//		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
+		//		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
+		//		super.visitMethodInsn(INVOKEVIRTUAL, 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.visitJumpInsn(Opcodes.IFNE, exists);
+		//		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
+		//		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
+		//		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
+		//		super.visitInsn(ICONST_0);
+		//		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Integer.class), "valueOf", "(I)Ljava/lang/Integer;");
+		//		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+		//		super.visitInsn(POP);
+		//		super.visitLabel(exists);
+		//		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
+		//		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
+		//		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
+		//		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
+		//		super.visitTypeInsn(CHECKCAST, "java/lang/Integer");
+		//		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Integer.class), "intValue", "()I");
+		Label load = new Label();
+		visitLabel(load);
+				super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
+				super.visitFieldInsn(GETSTATIC, className, fieldName + "_owners", "[Ljava/lang/String;");
+				super.visitFieldInsn(GETSTATIC, className, fieldName + "_fill", "I");
+				super.visitLdcInsn(className);
+				if(className.contains("Serializable"))
+					super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ReplayUtils.class), "getNextIndex", "(Ljava/util/HashMap;[Ljava/lang/String;ILjava/lang/String;)I");
+				else
+				{
+					super.visitFieldInsn(GETSTATIC, className, fieldName , "[Ljava/lang/Object;");
+
+					super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ReplayUtils.class), "getNextIndexO", "(Ljava/util/HashMap;[Ljava/lang/String;ILjava/lang/String;[Ljava/lang/Object;)I");
+				}
+				super.visitInsn(DUP);
+				Label cont = new Label();
+				super.visitJumpInsn(IFGE, cont);
+				super.visitInsn(POP);
+				super.visitLdcInsn(className);
+				super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ReplayRunner.class), "loadNextLog", "(Ljava/lang/String;)V");
+				super.visitJumpInsn(GOTO, load);
+				visitLabel(cont);
+//		super.visitInsn(ICONST_0);
 	}

 	private void incrementReplayIndex(String className, String fieldName) {
-		super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
-		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
-		loadReplayIndex(className, fieldName);
-		super.visitInsn(ICONST_1);
-		super.visitInsn(IADD);
-		super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Integer.class), "valueOf", "(I)Ljava/lang/Integer;");
-		super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-		super.visitInsn(POP);
+				super.visitFieldInsn(GETSTATIC, className, fieldName + "_replayIndex", "Ljava/util/HashMap;");
+				super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Thread.class), "currentThread", "()Ljava/lang/Thread;");
+				super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Thread.class), "getName", "()Ljava/lang/String;");
+				loadReplayIndex(className, fieldName);
+				super.visitInsn(ICONST_1);
+				super.visitInsn(IADD);
+				super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Integer.class), "valueOf", "(I)Ljava/lang/Integer;");
+				super.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(HashMap.class), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+				super.visitInsn(POP);
+
+				super.visitFieldInsn(GETSTATIC, Type.getInternalName(ExportedLog.class), "globalReplayIndex", "I");
+				super.visitInsn(ICONST_1);
+				super.visitInsn(IADD);
+				super.visitFieldInsn(PUTSTATIC, Type.getInternalName(ExportedLog.class), "globalReplayIndex", "I");
 	}

-	private HashMap<String, MethodInsnNode>	captureMethodsToGenerate	= new HashMap<String, MethodInsnNode>();
-
+	private HashMap<String, MethodInsnNode> captureMethodsToGenerate = new HashMap<String, MethodInsnNode>();
+	private boolean inited;
 	@Override
 	public void visitMethodInsn(int opcode, String owner, String name, String desc) {

 		try {
 			MethodCall m = new MethodCall(this.name, this.desc, this.classDesc, pc, lineNumber, owner, name, desc, isStatic);
 			Type returnType = Type.getMethodType(desc).getReturnType();
-
 			if (opcode == INVOKESPECIAL && name.equals("<init>") && NonDeterministicLoggingMethodVisitor.nonDeterministicMethods.contains(owner + "." + name + ":" + desc)) {

 				if (!(owner.equals(Replayer.instrumentedClasses.get(classDesc).superName) && this.name.equals("<init>"))) {
-					Type[] args = Type.getArgumentTypes(desc);
-					for (int i = args.length - 1; i >= 0; i--) {
-						Type t = args[i];
-						if (t.getSize() == 2)
-							mv.visitInsn(POP2);
-						else
-							mv.visitInsn(POP);
-					}
-
-					if (analyzer.stack != null && analyzer.stack.size() > 0
-							&& analyzer.uninitializedTypes.containsKey(analyzer.stack.get(analyzer.stack.size() - 1))
-							&& analyzer.uninitializedTypes.get(analyzer.stack.get(analyzer.stack.size() - 1)).equals(owner)) {
-						mv.visitInsn(POP);
-						if (analyzer.stack.size() > 0 && analyzer.uninitializedTypes.containsKey(analyzer.stack.get(analyzer.stack.size() - 1))
-								&& analyzer.uninitializedTypes.get(analyzer.stack.get(analyzer.stack.size() - 1)).equals(owner))
-							mv.visitInsn(POP);
+					if (analyzer.stack == null) {
+						super.visitMethodInsn(opcode, owner, name, desc);
+					} else {
+						Type[] args = Type.getArgumentTypes(desc);
+						for (int i = args.length - 1; i >= 0; i--) {
+							Type t = args[i];
+							if (t.getSize() == 2)
+								mv.visitInsn(POP2);
+							else
+								mv.visitInsn(POP);
+						}

-						String replayClassName = MethodCall.getReplayClassName(Type.getType("L"+m.getMethodOwner()+";"));
-						mv.visitFieldInsn(GETSTATIC, replayClassName, m.getLogFieldName(), "[Ljava/lang/Object;");
+						if (analyzer.stack != null && analyzer.stack.size() > 0 && analyzer.uninitializedTypes.containsKey(analyzer.stack.get(analyzer.stack.size() - 1))
+								&& analyzer.uninitializedTypes.get(analyzer.stack.get(analyzer.stack.size() - 1)).equals(owner)) {
+							mv.visitInsn(POP);
+							if (analyzer.stack.size() > 0 && analyzer.uninitializedTypes.containsKey(analyzer.stack.get(analyzer.stack.size() - 1))
+									&& analyzer.uninitializedTypes.get(analyzer.stack.get(analyzer.stack.size() - 1)).equals(owner))
+								mv.visitInsn(POP);

-						Label fallThrough = new Label();
-						loadReplayIndex(replayClassName, m.getLogFieldName());
-						mv.visitInsn(DUP);
+							String replayClassName = MethodCall.getReplayClassName(Type.getType("L" + m.getMethodOwner() + ";"));
+							mv.visitFieldInsn(GETSTATIC, replayClassName, m.getLogFieldName(), "[Ljava/lang/Object;");

-						mv.visitFieldInsn(GETSTATIC, replayClassName, m.getLogFieldName() + "_fill", "I");
-						mv.visitJumpInsn(Opcodes.IF_ICMPNE, fallThrough);
-						mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(ReplayRunner.class), "loadNextLog", "()V");
-						mv.visitInsn(POP);
-						loadReplayIndex(replayClassName, m.getLogFieldName());
+							loadReplayIndex(replayClassName, m.getLogFieldName());

-						mv.visitLabel(fallThrough);
-						//				arrayLoad(Type.getType("L"+m.getMethodOwner()+";"));
-						mv.visitInsn(AALOAD);
-						mv.visitTypeInsn(CHECKCAST, m.getMethodOwner());
-						incrementReplayIndex(replayClassName, m.getLogFieldName());
+							mv.visitInsn(AALOAD);
+							mv.visitTypeInsn(CHECKCAST, m.getMethodOwner());
+							incrementReplayIndex(replayClassName, m.getLogFieldName());
+						}
 					}
-
 				} else {
 					super.visitMethodInsn(opcode, owner, name, desc);
 				}
@@ -209,25 +232,25 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 						Type t = targs[i];
 						if (t.getSort() == Type.ARRAY) {
 							/*
-							 * stack (grows down): dest (fill not incremented yet)
+							 * stack (grows down): dest (fill not incremented
+							 * yet)
 							 */
 							String replayClassName = MethodCall.getReplayClassName(t);
 							String replayFieldName = MethodCall.getLogFieldName(t);
-							mv.visitFieldInsn(GETSTATIC, replayClassName, MethodCall.getLogFieldName(t), MethodCall.getLogFieldType(t)
-									.getDescriptor());
+							mv.visitFieldInsn(GETSTATIC, replayClassName, MethodCall.getLogFieldName(t), MethodCall.getLogFieldType(t).getDescriptor());
 							//							mv.visitFieldInsn(GETSTATIC,replayClassName,
 							//									MethodCall.getLogFieldName(t)+"_replayIndex",
 							//									"I");
 							loadReplayIndex(replayClassName, replayFieldName);
-							mv.visitInsn(DUP);
-							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();
-							loadReplayIndex(replayClassName, replayFieldName);
-							visitLabel(fallThrough);
+//							mv.visitInsn(DUP);
+//							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();
+//							loadReplayIndex(replayClassName, replayFieldName);
+//							visitLabel(fallThrough);

 							arrayLoad(t);

@@ -251,8 +274,7 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 							 * stack (grows down): src 0 dest 0
 							 */

-							mv.visitFieldInsn(GETSTATIC, replayClassName, MethodCall.getLogFieldName(t), MethodCall.getLogFieldType(t)
-									.getDescriptor());
+							mv.visitFieldInsn(GETSTATIC, replayClassName, MethodCall.getLogFieldName(t), MethodCall.getLogFieldType(t).getDescriptor());
 							loadReplayIndex(replayClassName, replayFieldName);
 							arrayLoad(t);
 							mv.visitTypeInsn(Opcodes.CHECKCAST, t.getInternalName());
@@ -280,16 +302,23 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im

 				} else {
 					Type[] targs = Type.getArgumentTypes(desc);
-					for (Type t : targs) {
-						switch (t.getSize()) {
-						case 2:
-							visitInsn(POP2);
-							break;
-						case 1:
-						default:
-							visitInsn(POP);
-							break;
-						}
+//					for (Type t : targs) {
+//						switch (t.getSize()) {
+//						case 2:
+//							visitInsn(POP2);
+//							break;
+//						case 1:
+//						default:
+//							visitInsn(POP);
+//							break;
+//						}
+//					}
+					for (int i = args.length - 1; i >= 0; i--) {
+						Type t = args[i];
+						if (t.getSize() == 2)
+							mv.visitInsn(POP2);
+						else
+							mv.visitInsn(POP);
 					}
 				}

@@ -302,15 +331,6 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 					mv.visitFieldInsn(GETSTATIC, m.getReplayClassName(), m.getLogFieldName(), m.getLogFieldType().getDescriptor());

 					loadReplayIndex(m.getReplayClassName(), m.getLogFieldName());
-					mv.visitInsn(DUP);
-					Label fallThrough = new Label();
-					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);
-					loadReplayIndex(m.getReplayClassName(), m.getLogFieldName());
-
-					mv.visitLabel(fallThrough);
 					arrayLoad(m.getReturnType());
 					incrementReplayIndex(m.getReplayClassName(), m.getLogFieldName());
 				}
@@ -325,9 +345,15 @@ public class NonDeterministicReplayMethodVisitor extends CloningAdviceAdapter im
 		} catch (Exception ex) {
 			logger.error("Unable to instrument method call", ex);
 		}
+		if(this.name.equals("<init>") && !inited && isCallbackInit)
+		{
+			loadThis();
+			super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(CallbackRegistry.class), "register", "(Ljava/lang/Object;)V");
+			inited = true;
+		}
 	}

-	private ArrayList<MethodCall>	methodCallsToClear	= new ArrayList<MethodCall>();
+	private ArrayList<MethodCall> methodCallsToClear = new ArrayList<MethodCall>();

 	@Override
 	public void visitFieldInsn(int opcode, String owner, String name, String desc) {
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/ReplayRunner.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/ReplayRunner.java
index e874348..c46ab43 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/ReplayRunner.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/ReplayRunner.java
@@ -10,11 +10,13 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
+import java.util.HashMap;

 import org.objectweb.asm.Type;

 import com.thoughtworks.xstream.XStream;

+import edu.columbia.cs.psl.wallace.CallbackInvocation;
 import edu.columbia.cs.psl.wallace.CloningUtils;
 import edu.columbia.cs.psl.wallace.Constants;
 import edu.columbia.cs.psl.wallace.ExportedLog;
@@ -49,6 +51,16 @@ public class ReplayRunner {
 				XStream xstream = new XStream(new StaticReflectionProvider());
 				Object o = xstream.fromXML(new File(logFiles[nextLog]));
 				nextLog++;
+
+				ReplayUtils.dispatchesToRun = new HashMap<Integer,CallbackInvocation>();
+				for(Object e : ExportedLog.aLog)
+				{
+					if(e != null && e.getClass().equals(CallbackInvocation.class))
+					{
+						CallbackInvocation ci = (CallbackInvocation) e;
+						ReplayUtils.dispatchesToRun.put(ci.getClock(), ci);
+					}
+				}
 			}
 		} catch (Exception exi) {
 			exi.printStackTrace();
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/Replayer.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/Replayer.java
index a2a209a..373b877 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/Replayer.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/replay/Replayer.java
@@ -146,8 +146,8 @@ public class Replayer {
 			lastInstrumentedClass = cv.getClassName();
 			byte[] out = cw.toByteArray();
 			try{
-				 ClassReader cr2 = new ClassReader(out);
-				 cr2.accept(new CheckClassAdapter(new ClassWriter(0)), 0);
+//				 ClassReader cr2 = new ClassReader(out);
+//				 cr2.accept(new CheckClassAdapter(new ClassWriter(0)), 0);
 				}
 				catch(Exception ex)
 				{
@@ -355,7 +355,19 @@ public class Replayer {
 							jos.putNextEntry(outEntry);
 							byte[] clazz = instrumentClass(jar
 									.getInputStream(e));
-							jos.write(clazz);
+							if(clazz == null)
+							{
+								InputStream is = jar.getInputStream(e);
+								byte[] buffer = new byte[1024];
+								while (true) {
+									int count = is.read(buffer);
+									if (count == -1)
+										break;
+									jos.write(buffer, 0, count);
+								}
+							}
+							else
+									jos.write(clazz);
 							jos.closeEntry();
 						}
 						{
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/CloningAdviceAdapter.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/CloningAdviceAdapter.java
index 4be9f24..ece33e8 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/CloningAdviceAdapter.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/CloningAdviceAdapter.java
@@ -101,14 +101,12 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 		// 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");
+			 println("reference> " + debug);
 			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();
@@ -116,14 +114,6 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 				ifNull(nullContinue);
 				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);
@@ -293,8 +283,13 @@ public class CloningAdviceAdapter extends GeneratorAdapter implements Opcodes {
 		visitFieldInsn(getOpcode, logFieldOwner, logFieldName+"_owners", "[Ljava/lang/String;");
 		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;");
+		if(debug.startsWith("callback"))
+			visitLdcInsn("callback-handler");
+		else
+		{
+			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());

diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/NonDeterministicLoggingClassVisitor.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/NonDeterministicLoggingClassVisitor.java
index 89c94cd..fa176d3 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/NonDeterministicLoggingClassVisitor.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/visitor/NonDeterministicLoggingClassVisitor.java
@@ -1,9 +1,12 @@
 package edu.columbia.cs.psl.wallace.visitor;

+import java.io.File;
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Scanner;

 import org.apache.log4j.Logger;
 import org.objectweb.asm.ClassVisitor;
@@ -14,9 +17,13 @@ import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.AnalyzerAdapter;
 import org.objectweb.asm.commons.JSRInlinerAdapter;
 import org.objectweb.asm.commons.LocalVariablesSorter;
+import org.objectweb.asm.tree.ClassNode;
 import org.objectweb.asm.tree.MethodInsnNode;

+import com.sun.corba.se.impl.resolver.INSURLOperationImpl;
+
 import edu.columbia.cs.psl.wallace.Constants;
+import edu.columbia.cs.psl.wallace.Instrumenter;
 import edu.columbia.cs.psl.wallace.MethodCall;

 public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements Opcodes {
@@ -24,6 +31,24 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 	private String className;
 	private boolean isAClass = true;

+	public static HashSet<String> callbackClasses = new HashSet<String>();
+	public static HashSet<String> callbackMethods = new HashSet<String>();
+	static
+	{
+		File f = new File("listenerMethods.txt");
+		Scanner s;
+		try {
+			s = new Scanner(f);
+			while (s.hasNextLine())
+			{
+				String l = s.nextLine();
+				callbackMethods.add(l);
+				callbackClasses.add(l.substring(0,l.indexOf(".")));
+			}
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		}
+	}
 	public NonDeterministicLoggingClassVisitor(int api, ClassVisitor cv) {
 		super(api, cv);

@@ -43,6 +68,39 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements

 	private boolean isFirstConstructor = true;

+	private boolean classIsCallback(String className)
+	{
+		if(callbackClasses.contains(className))
+			return true;
+		if(!Instrumenter.instrumentedClasses.containsKey(className))
+			return false;
+		ClassNode cn = Instrumenter.instrumentedClasses.get(className);
+		for(Object s : cn.interfaces)
+		{
+			if(callbackClasses.contains(((String)s)))
+				return true;
+		}
+		return classIsCallback(cn.superName);
+	}
+	public static boolean methodIsCallback(String className, String name, String desc)
+	{
+		if(name.equals("warning"))
+		{
+			System.out.println(name);
+		}
+		String key = "."+name +":"+desc;
+		if(callbackMethods.contains(className + key))
+			return true;
+		if(!Instrumenter.instrumentedClasses.containsKey(className))
+			return false;
+		ClassNode cn = Instrumenter.instrumentedClasses.get(className);
+		for(Object s : cn.interfaces)
+		{
+			if(callbackMethods.contains(((String)s) + key))
+				return true;
+		}
+		return methodIsCallback(cn.superName, name, desc);
+	}
 	@Override
 	public MethodVisitor visitMethod(int acc, String name, String desc, String signature, String[] exceptions) {
 		// TODO need an annotation to disable doing this to some apps
@@ -52,14 +110,22 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 		{
 			smv = new MainLoggingMethodVisitor(Opcodes.ASM4, primaryMV, acc, name, desc, className);
 		}
+
+		if(classIsCallback(className))
+		{
+			AnalyzerAdapter analyzer = new AnalyzerAdapter(className, acc, name, desc, smv);
+			CloningAdviceAdapter caa = new CloningAdviceAdapter(Opcodes.ASM4, analyzer, acc, name, desc, className, null);
+			smv = new CallbackLoggingMethodVisitor(Opcodes.ASM4,analyzer, acc, name, desc, className, null,caa);
+			smv = new JSRInlinerAdapter(smv, acc, name, desc, signature, exceptions);
+
+		}
 		if (isAClass && !name.equals(Constants.INNER_COPY_METHOD_NAME) && !name.equals(Constants.OUTER_COPY_METHOD_NAME) && !name.equals(Constants.SET_FIELDS_METHOD_NAME)
 				&& !className.startsWith("com/thoughtworks")
 				)
 		{

-			JSRInlinerAdapter mv = new JSRInlinerAdapter(smv, acc, name, desc, signature, exceptions);
+			AnalyzerAdapter analyzer = new AnalyzerAdapter(className, acc, name, desc, smv);

-			AnalyzerAdapter analyzer = new AnalyzerAdapter(className, acc, name, desc, mv);
 //			LocalVariablesSorter sorter  = new LocalVariablesSorter(acc, desc, analyzer);

 			// CheckMethodAdapter cmv = new CheckMethodAdapter(mv);
@@ -68,7 +134,9 @@ public class NonDeterministicLoggingClassVisitor extends ClassVisitor implements
 			if (name.equals("<init>"))
 				isFirstConstructor = false;
 			cloningMV.setClassVisitor(this);
-			return cloningMV;
+			JSRInlinerAdapter mv = new JSRInlinerAdapter(cloningMV, acc, name, desc, signature, exceptions);
+
+			return mv;
 		} else
 			return smv;
 	}
diff --git a/testcase-generation/src/edu/columbia/cs/psl/wallace/xstream/StaticReflectionProvider.java b/testcase-generation/src/edu/columbia/cs/psl/wallace/xstream/StaticReflectionProvider.java
index 278b1fb..5f929bf 100644
--- a/testcase-generation/src/edu/columbia/cs/psl/wallace/xstream/StaticReflectionProvider.java
+++ b/testcase-generation/src/edu/columbia/cs/psl/wallace/xstream/StaticReflectionProvider.java
@@ -43,9 +43,9 @@ public class StaticReflectionProvider extends Sun14ReflectionProvider {
 			try {
 				Object value = field.get(object);
 				if (value != null)
-					synchronized (value) {
+//					synchronized (value) {
 						visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);
-					}
+//					}
 				else
 					visitor.visit(field.getName(), field.getType(), field.getDeclaringClass(), value);