diff --git a/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java b/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java index 700afcc..12ef3d2 100644 --- a/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java +++ b/TracerOnJavassist/src/tracer/OutputStatementsGenerator.java @@ -31,19 +31,26 @@ return generator; } - public String generateReplaceStatementsForFieldSet(CtClass cc, FieldAccess f, int line) { + public String generateReplaceStatementsForFieldSet(CtClass cc, FieldAccess f, int line) throws NotFoundException { String fieldName = "\"" + f.getClassName() + "." + f.getFieldName() + "\""; String containerClass = "(($0 != null)?$0.getClass().getName():\"" + cc.getName() + "\")"; String containerObject = "(($0 != null)?System.identityHashCode($0):0)"; - String valueClass = "(($1 != null)?$1.getClass().getName():\"---\")"; - String valueObject = "(($1 != null)?System.identityHashCode($1):0)"; + String valueClass; + String valueObject; + if (!f.getField().getType().isPrimitive()) { + valueClass = "(($1 != null)?$1.getClass().getName():\"---\")"; + valueObject = "(($1 != null)?System.identityHashCode($1):0)"; + } else { + valueClass = "\"" + f.getField().getType().getName() + "\""; // ��{�^�̏ꍇ�AgetClass()�ł��Ȃ����� + valueObject = "$1"; + } String threadId = "Thread.currentThread().getId()"; String lineNum = "\"" + line + "\""; String timeStamp = "System.nanoTime()"; return generator.generateReplaceStatementsForFieldSet(fieldName, containerClass, containerObject, valueClass, valueObject, threadId, lineNum, timeStamp); } - public String generateReplaceStatementsForFieldGet(CtClass cc, CtBehavior m, FieldAccess f, int line) { + public String generateReplaceStatementsForFieldGet(CtClass cc, CtBehavior m, FieldAccess f, int line) throws NotFoundException { String fieldName = "\"" + f.getClassName() + "." + f.getFieldName() + "\""; String thisClass; String thisObject; @@ -57,8 +64,15 @@ } String containerClass = "(($0 != null)?$0.getClass().getName():\"---\")"; String containerObject = "(($0 != null)?System.identityHashCode($0):0)"; - String valueClass = "(($_ != null)?$_.getClass().getName():\"---\")"; - String valueObject = "(($_ != null)?System.identityHashCode($_):0)"; + String valueClass; + String valueObject; + if (!f.getField().getType().isPrimitive()) { + valueClass = "(($_ != null)?$_.getClass().getName():\"---\")"; + valueObject = "(($_ != null)?System.identityHashCode($_):0)"; + } else { + valueClass = "\"" + f.getField().getType().getName() + "\""; // ��{�^�̏ꍇ�AgetClass()�ł��Ȃ����� + valueObject = "$_"; + } String threadId = "Thread.currentThread().getId()"; String lineNum = "\"" + line + "\""; String timeStamp = "System.nanoTime()"; @@ -222,7 +236,7 @@ thisClass = "this.getClass().getName()"; thisObject = "System.identityHashCode(this)"; } else { - returnedClass = "\"" + ((CtMethod)m).getReturnType().getName() +"\""; + returnedClass = "\"" + ((CtMethod)m).getReturnType().getName() +"\""; // ��{�^�̏ꍇ�AgetClass()�ł��Ȃ����� returnedObject = "$_"; thisClass = "this.getClass().getName()"; thisObject = "System.identityHashCode(this)"; @@ -235,7 +249,7 @@ thisClass = "$0.getClass().getName()"; thisObject = "System.identityHashCode($0)"; } else { - returnedClass = "\"" + ((CtMethod)m).getReturnType().getName() +"\""; + returnedClass = "\"" + ((CtMethod)m).getReturnType().getName() +"\""; // ��{�^�̏ꍇ�AgetClass()�ł��Ȃ����� returnedObject = "$_"; thisClass = "$0.getClass().getName()"; thisObject = "System.identityHashCode($0)"; diff --git a/TracerOnJavassist/src/tracer/Tracer.java b/TracerOnJavassist/src/tracer/Tracer.java index 3e468b3..6ac42b5 100644 --- a/TracerOnJavassist/src/tracer/Tracer.java +++ b/TracerOnJavassist/src/tracer/Tracer.java @@ -5,6 +5,7 @@ import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; +import java.util.List; import javassist.CannotCompileException; import javassist.ClassPool; @@ -15,8 +16,10 @@ import javassist.CtMethod; import javassist.NotFoundException; import javassist.bytecode.BadBytecode; +import javassist.bytecode.LineNumberAttribute; import javassist.bytecode.analysis.ControlFlow; import javassist.bytecode.analysis.ControlFlow.Block; +import javassist.bytecode.analysis.ControlFlow.Catcher; import javassist.expr.ExprEditor; import javassist.expr.FieldAccess; import javassist.expr.MethodCall; @@ -46,7 +49,7 @@ URL resource = loader.getResource(""); try { String classPath = URLDecoder.decode(resource.getPath(), "UTF-8"); - packageInstrumentation("_arraySample.", classPath); // �w�肵���p�b�P�[�W���̑S�N���X�ɃC���X�g�D�������e�[�V�������s�� + packageInstrumentation("_arraySample/", classPath); // �w�肵���p�b�P�[�W���̑S�N���X�ɃC���X�g�D�������e�[�V�������s�� } catch (UnsupportedEncodingException e) { e.printStackTrace(); } @@ -98,13 +101,13 @@ */ public static void packageInstrumentation(String packageName, String classPath) { File dir; - dir = new File(classPath + packageName.replace(".", "/")); + dir = new File(classPath + packageName); for (File file : dir.listFiles()) { if (file.isFile() && file.getName().endsWith(".class")) { - String className = packageName + file.getName().replace(".class", ""); + String className = packageName.replace("/", ".") + file.getName().replace(".class", ""); classInstrumentation(className, classPath); } else if (file.isDirectory()) { - packageInstrumentation(packageName + file.getName() + ".", classPath); + packageInstrumentation(packageName + file.getName() + "/", classPath); } } } @@ -118,7 +121,9 @@ public static void classInstrumentation(String className, String classPath) { try { CtClass cc = cp.get(className); - classInstrumentation(cc, classPath); +// cc.defrost(); +// cc.stopPruning(true); + if (!cc.isFrozen()) classInstrumentation(cc, classPath); } catch (NotFoundException | BadBytecode | CannotCompileException | IOException e) { e.printStackTrace(); } @@ -140,7 +145,17 @@ methodInstrumentation(cc, m); } cc.instrument(conv); - if (classPath != null) cc.writeFile(classPath); + if (classPath != null) { + if (classPath.endsWith("/")) { + classPath = classPath.substring(0, classPath.length() - 1); + } + System.out.println(classPath + ":" + cc.getName()); +// cc.rebuildClassFile(); + cc.getClassFile().compact(); // ���ꂪ�Ȃ��ƁA���s���� java.lang.ClassFormatError: Truncated class file �ŗ����� + cc.debugWriteFile(classPath); +// cc.defrost(); + cc.detach(); + } } private static void classInitializerInstrumentation(CtClass cc, CtConstructor classInitializer) throws BadBytecode, NotFoundException, CannotCompileException { @@ -158,23 +173,66 @@ if (m instanceof CtMethod && !m.isEmpty()) { ControlFlow cf = new ControlFlow((CtMethod)m); blocks = cf.basicBlocks(); + List list = m.getMethodInfo().getCodeAttribute().getAttributes(); + LineNumberAttribute attr = null; + for (int i = 0; i < list.size(); i++) { + if (list.get(i) instanceof LineNumberAttribute){ + attr = (LineNumberAttribute)list.get(i); + break; + } + } + int[] lines = new int[blocks.length]; + for (int i = 0; i < blocks.length; i++) { + int pos = blocks[i].position(); + int line = m.getMethodInfo().getLineNumber(pos); + if (attr != null && pos != attr.toStartPc(line)) { + lines[i] = -1; + } else { + lines[i] = line; + } + } for (int i = blocks.length - 1; i >= 0; i--) { - int blockPos = m.getMethodInfo().getLineNumber(blocks[i].position()); - m.insertAt(blockPos, outputStatementsGenerator.generateInsertStatementsForBlockEntry((CtMethod)m, i, blocks[i], blockPos)); + for (int j = 0; j < i; j++) { + if (lines[j] == lines[i]) { + lines[i] = -1; + break; + } + if (blocks[j].catchers().length > 0) { + for (Catcher c: blocks[j].catchers()) { + if (m.getMethodInfo().getLineNumber(c.block().position()) == lines[i]) { + lines[i] = -1; + break; + } + } + if (lines[i] == i) break; + } + } + if (lines[i] != -1) { + String code = outputStatementsGenerator.generateInsertStatementsForBlockEntry((CtMethod)m, i, blocks[i], lines[i]); + try { + m.insertAt(lines[i], code); + } catch (CannotCompileException e) { + System.out.println(m.getLongName() + ":" + lines[i] + ":" + blocks[i].catchers().length + ":" + code); + } + } } } // ���\�b�h�{�̓��̃t�B�[���h�A�N�Z�X�ƃ��\�b�h�Ăяo����u�������� m.instrument(new ExprEditor() { public void edit(FieldAccess f) throws CannotCompileException { - if (f.isReader()) { - if (!f.getFieldName().contains("$")) { // AspectJ�ł� final local �ϐ�����̃Q�b�g�͖��������̂ŁA����ɍ��킹�ď��O���� - f.replace(outputStatementsGenerator.generateReplaceStatementsForFieldGet(cc, m, f, f.getLineNumber())); + try { + if (f.isReader()) { + if (!f.getFieldName().contains("$")) { // AspectJ�ł� final local �ϐ�����̃Q�b�g�͖��������̂ŁA����ɍ��킹�ď��O���� + f.replace(outputStatementsGenerator.generateReplaceStatementsForFieldGet(cc, m, f, f.getLineNumber())); + } + } else { + if (!f.getFieldName().contains("$")) { // ���̏������Ȃ��ƂȂ���������i�����t�B�[���h?�ւ̃Z�b�g�������āA������E���ė����Ă�?�j + f.replace(outputStatementsGenerator.generateReplaceStatementsForFieldSet(cc, f, f.getLineNumber())); + } } - } else { - if (!f.getFieldName().contains("$")) { // ���̏������Ȃ��ƂȂ���������i�����t�B�[���h?�ւ̃Z�b�g�������āA������E���ė����Ă�?�j - f.replace(outputStatementsGenerator.generateReplaceStatementsForFieldSet(cc, f, f.getLineNumber())); - } + } catch (NotFoundException e) { + e.printStackTrace(); } } public void edit(MethodCall c) throws CannotCompileException { @@ -234,5 +292,8 @@ m.insertBefore(outputStatementsGenerator.generateInsertBeforeStatementsForMethodBody(cc, m)); } } + if (m.getMethodInfo().getCodeAttribute() != null) { + m.getMethodInfo().getCodeAttribute().computeMaxStack(); // ���ꂪ�Ȃ��ƁA���s���� java.lang.VerifyError: Stack map does not match the one at exception handler... �ŗ����� + } } } diff --git a/TracerOnJavassist/src/tracer/TracerClassLoader.java b/TracerOnJavassist/src/tracer/TracerClassLoader.java index d7e2eeb..add77f1 100644 --- a/TracerOnJavassist/src/tracer/TracerClassLoader.java +++ b/TracerOnJavassist/src/tracer/TracerClassLoader.java @@ -13,10 +13,10 @@ @Override protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (!Tracer.isInitialized()) Tracer.initialize(new OutputStatementsGenerator(new JSONTraceGenerator())); // �����ŏo�̓t�H�[�}�b�g���w�肷�� + Tracer.initialize(new OutputStatementsGenerator(new JSONTraceGenerator())); // �����ŏo�̓t�H�[�}�b�g���w�肷�� // "java"�Ŏn�܂�p�b�P�[�W�̓V�X�e���n�Ȃ̂Ńf�t�H���g�̃N���X���[�_�[�ɔC���� - if (name.startsWith("java") || name.startsWith("sun.") || name.startsWith(Tracer.TRACER)) { + if (name.startsWith("java") || name.startsWith("sun.") || name.startsWith("com.sun.") || name.startsWith(Tracer.TRACER)) { return super.loadClass(name, resolve); }