diff --git a/TracerOnJavassist/src/tracer/ITraceGenerator.java b/TracerOnJavassist/src/tracer/ITraceGenerator.java index 364d98c..6257f2f 100644 --- a/TracerOnJavassist/src/tracer/ITraceGenerator.java +++ b/TracerOnJavassist/src/tracer/ITraceGenerator.java @@ -35,4 +35,8 @@ String returnedClass, String returnedObject, String threadId, String timeStamp, boolean isCallerSideInstrumentation); + + public abstract String generateReplaceStatementsForNewArray( + String arrayClass, String arrayObject, String dimension, + String threadId, String timeStamp); } diff --git a/TracerOnJavassist/src/tracer/JSONArrayAdvisor.java b/TracerOnJavassist/src/tracer/JSONArrayAdvisor.java new file mode 100644 index 0000000..3fa0c4b --- /dev/null +++ b/TracerOnJavassist/src/tracer/JSONArrayAdvisor.java @@ -0,0 +1,98 @@ +package tracer; + +import java.util.ArrayList; + +/** + * �z��ւ̃A�N�Z�X�����o�͂��邽�߂̃N���X + * @author �V�c���� + * + */ +public class JSONArrayAdvisor { + public static void arrayWriteInt(Object array, int index, int value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "int", Integer.toString(value)); + ((int [])array)[index] = value; + } + + public static int arrayReadInt(Object array, int index) { + int value = ((int [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "int", Integer.toString(value)); + return value; + } + + public static void arrayWriteLong(Object array, int index, long value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "long", Long.toString(value)); + ((long [])array)[index] = value; + } + + public static long arrayReadLong(Object array, int index) { + long value = ((long [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "long", Long.toString(value)); + return value; + } + + public static void arrayWriteFloat(Object array, int index, float value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "float", Float.toString(value)); + ((float [])array)[index] = value; + } + + public static float arrayReadFloat(Object array, int index) { + float value = ((float [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "float", Float.toString(value)); + return value; + } + + public static void arrayWriteDouble(Object array, int index, double value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "double", Double.toString(value)); + ((double [])array)[index] = value; + } + + public static double arrayReadDouble(Object array, int index) { + double value = ((double [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "double", Double.toString(value)); + return value; + } + + public static void arrayWriteShort(Object array, int index, short value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "short", Short.toString(value)); + ((short [])array)[index] = value; + } + + public static short arrayReadShort(Object array, int index) { + short value = ((short [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "short", Short.toString(value)); + return value; + } + + public static void arrayWriteChar(Object array, int index, char value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "char", Character.toString(value)); + ((char [])array)[index] = value; + } + + public static char arrayReadChar(Object array, int index) { + char value = ((char [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "char", Character.toString(value)); + return value; + } + + public static void arrayWriteByteOrBoolean(Object array, int index, byte value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "byte", Byte.toString(value)); + ((byte [])array)[index] = value; + } + + public static byte arrayReadByteOrBoolean(Object array, int index) { + byte value = ((byte [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, "byte", Byte.toString(value)); + return value; + } + + public static void arrayWriteObject(Object array, int index, Object value) { + JSONTraceGenerator.arraySetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, value.getClass().getName(), Integer.toString(System.identityHashCode(value))); + ((Object [])array)[index] = value; + } + + public static Object arrayReadObject(Object array, int index) { + Object value = ((Object [])array)[index]; + JSONTraceGenerator.arrayGetOutput(array.getClass().getName(), Integer.toString(System.identityHashCode(array)), index, value.getClass().getName(), Integer.toString(System.identityHashCode(value))); + return value; + } +} diff --git a/TracerOnJavassist/src/tracer/JSONTraceGenerator.java b/TracerOnJavassist/src/tracer/JSONTraceGenerator.java index 7e8181d..da164d9 100644 --- a/TracerOnJavassist/src/tracer/JSONTraceGenerator.java +++ b/TracerOnJavassist/src/tracer/JSONTraceGenerator.java @@ -8,6 +8,11 @@ import javassist.CtClass; import javassist.CtConstructor; +/** + * JSON�g���[�X�o�͗p�̎��s�������� + * @author Nitta + * + */ public class JSONTraceGenerator implements ITraceGenerator { private static final String DQ_GEN = "\"\\\"\""; @@ -46,6 +51,22 @@ return "{$_ = $proceed(); " + "tracer.MyPrintStream.println(" + generateJSONMapGenerator(keys, values) + " + \",\");}"; } + + + @Override + public String generateReplaceStatementsForNewArray( + String arrayClass, String arrayObject, String dimension, + String threadId, String timeStamp) { + ArrayList keys = new ArrayList<>(); + ArrayList values = new ArrayList<>(); + keys.add("type"); values.add(DQ_GEN + " + \"arrayCreate\" + " + DQ_GEN); + keys.add("array"); values.add(generateJSONObjectGenerator(arrayClass, arrayObject)); + keys.add("dimension"); values.add(dimension); + keys.add("threadId"); values.add(threadId); + keys.add("time"); values.add(timeStamp); + return "{$_ = $proceed($$); " + + "tracer.MyPrintStream.println(" + generateJSONMapGenerator(keys, values) + " + \",\");}"; + } @Override public String generateInsertBeforeStatements( @@ -126,4 +147,43 @@ arrayJSON += " + \"]\""; return arrayJSON; } + + public static void arraySetOutput(String arrayType, String arrayId, int index, String valueType, String valueId) { + ArrayList keys = new ArrayList(); + ArrayList values = new ArrayList(); + keys.add("type"); values.add("\"arraySet\""); + keys.add("array"); values.add(generateJSONObjectOutput(arrayType, arrayId)); + keys.add("index"); values.add(Integer.toString(index)); + keys.add("value"); values.add(generateJSONObjectOutput(valueType, valueId)); + MyPrintStream.println(generateJSONMapOutput(keys, values) + ","); + } + + public static void arrayGetOutput(String arrayType, String arrayId, int index, String valueType, String valueId) { + ArrayList keys = new ArrayList(); + ArrayList values = new ArrayList(); + keys.add("type"); values.add("\"arrayGet\""); + keys.add("array"); values.add(generateJSONObjectOutput(arrayType, arrayId)); + keys.add("index"); values.add(Integer.toString(index)); + keys.add("value"); values.add(generateJSONObjectOutput(valueType, valueId)); + MyPrintStream.println(generateJSONMapOutput(keys, values) + ","); + } + + private static String generateJSONObjectOutput(String className, String objectId) { + ArrayList keys = new ArrayList(); + ArrayList values = new ArrayList(); + keys.add("class"); values.add("\"" + className + "\""); + keys.add("id"); values.add(objectId); + return generateJSONMapOutput(keys, values); + } + + private static String generateJSONMapOutput(ArrayList keys, ArrayList valueGenerators) { + String mapJSON = "{"; + String delimiter = ""; + for (int i = 0; i < keys.size(); i++) { + mapJSON += delimiter + "\"" + keys.get(i) + "\":" + valueGenerators.get(i); + delimiter = ","; + } + mapJSON += "}"; + return mapJSON; + } } diff --git a/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java b/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java index f820145..ddf8a53 100644 --- a/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java +++ b/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java @@ -9,6 +9,7 @@ import javassist.Modifier; import javassist.NotFoundException; import javassist.expr.FieldAccess; +import javassist.expr.NewArray; /** * �g���[�X�o�͂��s�����s���𐶐�����N���X�i�t�H�[�}�b�g�ˑ�������ITraceGenerator�Ɉڏ��j @@ -22,6 +23,10 @@ public OutputStatementsGenerator(ITraceGenerator generator) { this.generator = generator; } + + public ITraceGenerator getGenerator() { + return generator; + } public String generateReplaceStatementsForFieldSet(CtClass cc, FieldAccess f) { String fieldName = "\"" + f.getClassName() + "." + f.getFieldName() + "\""; @@ -55,6 +60,15 @@ return generator.generateReplaceStatementsForFieldGet(fieldName, thisClass, thisObject, containerClass, containerObject, valueClass, valueObject, threadId, timeStamp); } + + public String generateReplaceStatementsForNewArray(NewArray a) { + String arrayClass = "(($_ != null)?$_.getClass().getName():\"---\")"; + String arrayObject = "(($_ != null)?System.identityHashCode($_):0)"; + String dimension = "\"" + Integer.toString(a.getDimension()) + "\""; + String threadId = "Thread.currentThread().getId()"; + String timeStamp = "System.nanoTime()"; + return generator.generateReplaceStatementsForNewArray(arrayClass, arrayObject, dimension, threadId, timeStamp); + } public String generateReplaceStatementsForCall(CtClass cls, CtBehavior m) throws NotFoundException { return "{" + generateInsertBeforeStatements(cls, m, true) + " $_ = $proceed($$); " + generateInsertAfterStatements(cls, m, true) + "}"; diff --git a/TracerOnJavassist/src/tracer/PlainTextTraceGenerator.java b/TracerOnJavassist/src/tracer/PlainTextTraceGenerator.java index c65c7c8..6713f9b 100644 --- a/TracerOnJavassist/src/tracer/PlainTextTraceGenerator.java +++ b/TracerOnJavassist/src/tracer/PlainTextTraceGenerator.java @@ -6,6 +6,11 @@ import javassist.CtClass; import javassist.CtConstructor; +/** + * �]���̃g���[�X�o�͗p�̎��s�������� + * @author Nitta + * + */ public class PlainTextTraceGenerator implements ITraceGenerator { public static final String LINE_AND_THREAD = "\":Line \" + (tracer.Tracer.lineNo++) + \":ThreadNo \" + "; public static final String LINE = "\":Line \" + (tracer.Tracer.lineNo++) + \":\""; @@ -30,6 +35,13 @@ } @Override + public String generateReplaceStatementsForNewArray( + String arrayClass, String arrayObject, String dimension, + String threadId, String timeStamp) { + return "$_ = $proceed($$);"; + } + + @Override public String generateInsertBeforeStatements(CtBehavior m, String methodSignature, String thisClass, String thisObject, List argClasses, List argObjects, diff --git a/TracerOnJavassist/src/tracer/Tracer.java b/TracerOnJavassist/src/tracer/Tracer.java index 9baa5ce..adcf302 100644 --- a/TracerOnJavassist/src/tracer/Tracer.java +++ b/TracerOnJavassist/src/tracer/Tracer.java @@ -5,25 +5,20 @@ import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; -import java.util.Enumeration; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CodeConverter; -import javassist.CodeConverter.ArrayAccessReplacementMethodNames; import javassist.CtBehavior; import javassist.CtClass; import javassist.CtConstructor; -import javassist.CtField; import javassist.CtMethod; import javassist.NotFoundException; import javassist.bytecode.BadBytecode; -import javassist.bytecode.analysis.ControlFlow; -import javassist.bytecode.analysis.ControlFlow.Block; -import javassist.expr.ConstructorCall; import javassist.expr.ExprEditor; import javassist.expr.FieldAccess; import javassist.expr.MethodCall; +import javassist.expr.NewArray; import javassist.expr.NewExpr; /** @@ -37,12 +32,27 @@ private static final String STANDARD_CLASSES = "java.util.ListIterator|java.util.Iterator|java.util.List|java.util.Vector|java.util.ArrayList|java.util.Stack|java.util.Map|java.util.HashMap|java.util.Set|java.util.HashSet|java.util.Hashtable|java.util.LinkedList|java.lang.Thread"; private static final String CONCRETE_STANDARD_CLASSES = "java.util.Vector|java.util.ArrayList|java.util.Stack |java.util.HashMap|java.util.HashSet|java.util.Hashtable|java.util.LinkedList|java.lang.Thread"; private static OutputStatementsGenerator outputStatementsGenerator = null; + private static CodeConverter conv = new CodeConverter(); public static void main(String[] args) { - outputStatementsGenerator = new OutputStatementsGenerator(new JSONTraceGenerator()); // �����ŏo�̓t�H�[�}�b�g���w�肷�� + outputStatementsGenerator = new OutputStatementsGenerator(new PlainTextTraceGenerator()); // �����ŏo�̓t�H�[�}�b�g���w�肷�� String packageName = "arraySample"; // �w�肵���p�b�P�[�W�����̑S�N���X�ɃC���X�g�D�������e�[�V�������s�� ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL resource = loader.getResource(packageName); + + // �z��ւ̃A�N�Z�X�̌��o + if (!(outputStatementsGenerator.getGenerator() instanceof PlainTextTraceGenerator)) { + // + ClassPool cp = ClassPool.getDefault(); + CtClass cc; + try { + cc = cp.get("tracer.JSONArrayAdvisor"); // JSON�̏ꍇ�̂ݔz��A�N�Z�X���o�͂��� + conv.replaceArrayAccess(cc, new CodeConverter.DefaultArrayAccessReplacementMethodNames()); + } catch (NotFoundException e1) { + e1.printStackTrace(); + } + } + File dir; try { dir = new File(URLDecoder.decode(resource.getPath(), "UTF-8")); @@ -74,6 +84,7 @@ for (final CtMethod m : cc.getDeclaredMethods()) { methodInstrumentation(cc, m); } + cc.instrument(conv); cc.writeFile("bin"); } catch (NotFoundException | BadBytecode | CannotCompileException | IOException e) { e.printStackTrace(); @@ -119,6 +130,9 @@ e.printStackTrace(); } } + public void edit(NewArray a) throws CannotCompileException { + a.replace(outputStatementsGenerator.generateReplaceStatementsForNewArray(a)); + } // public void edit(ConstructorCall c) throws CannotCompileException { // try { // CtConstructor m = c.getConstructor(); @@ -143,75 +157,6 @@ m.insertBefore(outputStatementsGenerator.generateInsertBeforeStatementsForMethodBody(cc, m)); } } - - // CodeConverter conv = new CodeConverter(); - // conv.replaceArrayAccess(cc, new - // ArrayAccessReplacementMethodNames() { - // @Override - // public String shortWrite() { - // return null; - // } - // @Override - // public String shortRead() { - // return null; - // } - // @Override - // public String objectWrite() { - // return null; - // } - // @Override - // public String objectRead() { - // return null; - // } - // @Override - // public String longWrite() { - // return null; - // } - // @Override - // public String longRead() { - // return null; - // } - // @Override - // public String intWrite() { - // return null; - // } - // @Override - // public String intRead() { - // return null; - // } - // @Override - // public String floatWrite() { - // return null; - // } - // @Override - // public String floatRead() { - // return null; - // } - // @Override - // public String doubleWrite() { - // return null; - // } - // @Override - // public String doubleRead() { - // return null; - // } - // @Override - // public String charWrite() { - // return null; - // } - // @Override - // public String charRead() { - // return null; - // } - // @Override - // public String byteOrBooleanWrite() { - // return null; - // } - // @Override - // public String byteOrBooleanRead() { - // return null; - // } - // }); // Block[] blocks = cf.basicBlocks(); // int block0 = m.getMethodInfo().getLineNumber(blocks[0].position()); // int block1 =