diff --git a/JavassistTest/src/finalLocal/Main.java b/JavassistTest/src/finalLocal/Main.java new file mode 100644 index 0000000..5afdc64 --- /dev/null +++ b/JavassistTest/src/finalLocal/Main.java @@ -0,0 +1,32 @@ +package finalLocal; + +public class Main { + + /** + * @param args + */ + public static void main(String[] args) { + Main m = new Main(); + m.coordinator(); + } + + static class A { + int get() { + return 2; + } + } + + public void coordinator() { + final A a = new A(); + class Test { + private A a2; + + public void test() { + a2 = a; + System.out.println(a2.get()); + } + } + Test t = new Test(); + t.test(); + } +} diff --git a/JavassistTest/src/threadSample/A.java b/JavassistTest/src/threadSample/A.java new file mode 100644 index 0000000..c66b121 --- /dev/null +++ b/JavassistTest/src/threadSample/A.java @@ -0,0 +1,10 @@ +package threadSample; + +public class A { + B b = new B(); + D d = new D(); + + public void m() { + d.setC(b.getC()); + } +} diff --git a/JavassistTest/src/threadSample/B.java b/JavassistTest/src/threadSample/B.java new file mode 100644 index 0000000..a0b32fa --- /dev/null +++ b/JavassistTest/src/threadSample/B.java @@ -0,0 +1,10 @@ +package threadSample; + +public class B { + C c = new C(); + + public C getC() { + return c; + } + +} diff --git a/JavassistTest/src/threadSample/C.java b/JavassistTest/src/threadSample/C.java new file mode 100644 index 0000000..b533120 --- /dev/null +++ b/JavassistTest/src/threadSample/C.java @@ -0,0 +1,5 @@ +package threadSample; + +public class C { + +} diff --git a/JavassistTest/src/threadSample/D.java b/JavassistTest/src/threadSample/D.java new file mode 100644 index 0000000..b847233 --- /dev/null +++ b/JavassistTest/src/threadSample/D.java @@ -0,0 +1,10 @@ +package threadSample; + +public class D { + C c; + + public void setC(C c) { + this.c = c; + } + +} diff --git a/JavassistTest/src/threadSample/Main.java b/JavassistTest/src/threadSample/Main.java new file mode 100644 index 0000000..152bb73 --- /dev/null +++ b/JavassistTest/src/threadSample/Main.java @@ -0,0 +1,15 @@ +package threadSample; + +import threadSample.ThreadSample; + +public class Main { + + /** + * @param args + */ + public static void main(String[] args) { + Thread thread = new ThreadSample(); + thread.start(); + } + +} diff --git a/JavassistTest/src/threadSample/ThreadSample.java b/JavassistTest/src/threadSample/ThreadSample.java new file mode 100644 index 0000000..a6d5d23 --- /dev/null +++ b/JavassistTest/src/threadSample/ThreadSample.java @@ -0,0 +1,14 @@ +package threadSample; + +public class ThreadSample extends Thread { + public void run() { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + A a = new A(); + a.m(); + } + }); + thread.start(); + } +} diff --git a/JavassistTest/src/tracer/Tracer.java b/JavassistTest/src/tracer/Tracer.java index 3884e00..26a6ace 100644 --- a/JavassistTest/src/tracer/Tracer.java +++ b/JavassistTest/src/tracer/Tracer.java @@ -21,17 +21,20 @@ 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; public class Tracer { public static int lineNo = 1; - private static final String lineAndThread = "\":Line \" + (tracer.Tracer.lineNo++) + \":ThreadNo \" + Thread.currentThread().getId()"; - private static final String line = "\":Line \" + (tracer.Tracer.lineNo++) + \":\""; + private static final String LINE_AND_THREAD = "\":Line \" + (tracer.Tracer.lineNo++) + \":ThreadNo \" + Thread.currentThread().getId()"; + private static final String LINE = "\":Line \" + (tracer.Tracer.lineNo++) + \":\""; + 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"; public static void main(String[] args) { - String packageName = "sample"; // �w�肵���p�b�P�[�W�����̑S�N���X�ɃC���X�g�D�������e�[�V�������s�� + String packageName = "finalLocal"; // �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); File dir; @@ -79,125 +82,78 @@ final String declaredClassName = cc.getName(); String methodSignature = m.getSignature(); + // ���\�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()) { - String thisOutput = ""; - if ((m.getModifiers() & Modifier.STATIC) == 0 && m instanceof CtMethod) { - thisOutput = "tracer.MyPrintStream.print(\"get:\" + this.getClass().getName() + \":\" + System.identityHashCode(this) + \":\"); "; - } else { - // static���\�b�h���R���X�g���N�^�̏ꍇ - thisOutput = "tracer.MyPrintStream.print(\"get:" + declaredClassName + ":0:\"); "; + if (!f.getFieldName().contains("$")) { // AspectJ�ł� final local �ϐ�����̃Q�b�g�͖��������̂ŁA����ɍ��킹�ď��O���� + String thisOutput = ""; + if ((m.getModifiers() & Modifier.STATIC) == 0 && m instanceof CtMethod) { + thisOutput = "tracer.MyPrintStream.print(\"get:\" + this.getClass().getName() + \":\" + System.identityHashCode(this) + \":\"); "; + } else { + // static���\�b�h���R���X�g���N�^�̏ꍇ + thisOutput = "tracer.MyPrintStream.print(\"get:" + declaredClassName + ":0:\"); "; + } + f.replace("{$_ = $proceed(); " + + thisOutput + + "if ($0 != null) {" + // target + "tracer.MyPrintStream.print($0.getClass().getName() + \":\" + System.identityHashCode($0) + \":\"); " + + "} else {" + + "tracer.MyPrintStream.print(\"---:0:\"); " + + "} " + + "if ($_ != null) {" + // o + "tracer.MyPrintStream.println($_.getClass().getName() + \":\" + System.identityHashCode($_) + " + LINE_AND_THREAD + ");" + + "} else {" + + "tracer.MyPrintStream.println(\"---:0\" + " + LINE_AND_THREAD + ");" + + "} " + "}"); } - f.replace("{$_ = $proceed(); " + - thisOutput + - "if ($0 != null) {" + // target - "tracer.MyPrintStream.print($0.getClass().getName() + \":\" + System.identityHashCode($0) + \":\"); " + - "} else {" + - "tracer.MyPrintStream.print(\"---:0:\"); " + - "} " + - "if ($_ != null) {" + // o - "tracer.MyPrintStream.println($_.getClass().getName() + \":\" + System.identityHashCode($_) + " + lineAndThread + ");" + - "} else {" + - "tracer.MyPrintStream.println(\"---:0\" + " + lineAndThread + ");" + - "} " + "}"); } else { - f.replace("{$proceed($$); " + - "if ($0 != null) {" + // target - "tracer.MyPrintStream.print(\"set:\" + $0.getClass().getName() + \":\" + System.identityHashCode($0) + \":\"); " + - "} else {" + - "tracer.MyPrintStream.print(\"set:" + declaredClassName + ":0:\"); " + - "} " + - "if ($1 != null) {" + // o[0] - "tracer.MyPrintStream.println($1.getClass().getName() + \":\" + System.identityHashCode($1) + " + lineAndThread + ");" + - "} else {" + - "tracer.MyPrintStream.println(\"---:0\" + " + lineAndThread + ");" + - "}" + "}"); + if (!f.getFieldName().contains("$")) { // ���̏������Ȃ��ƂȂ���������i�����t�B�[���h?�ւ̃Z�b�g�������āA������E���ė����Ă�?�j + f.replace("{$proceed($$); " + + "if ($0 != null) {" + // target + "tracer.MyPrintStream.print(\"set:\" + $0.getClass().getName() + \":\" + System.identityHashCode($0) + \":\"); " + + "} else {" + + "tracer.MyPrintStream.print(\"set:" + declaredClassName + ":0:\"); " + + "} " + + "if ($1 != null) {" + // o[0] + "tracer.MyPrintStream.println($1.getClass().getName() + \":\" + System.identityHashCode($1) + " + LINE_AND_THREAD + ");" + + "} else {" + + "tracer.MyPrintStream.println(\"---:0\" + " + LINE_AND_THREAD + ");" + + "}" + "}"); + } + } + } + public void edit(MethodCall c) throws CannotCompileException { + try { + if (c.getMethod().getDeclaringClass().getName().matches(STANDARD_CLASSES)) { + CtMethod m = c.getMethod(); + Outputs out = generateOutputs(m.getDeclaringClass(), m, true); + c.replace("{" + out.newOutput + out.methodOutput + out.classOutput + out.argsOutput + " $_ = $proceed($$); " + out.returnOutput + "}"); + } + } catch (NotFoundException e) { + e.printStackTrace(); + } + } + public void edit(ConstructorCall c) throws CannotCompileException { + try { + if (c.getConstructor().getDeclaringClass().getName().matches(CONCRETE_STANDARD_CLASSES)) { + CtConstructor m = c.getConstructor(); + Outputs out = generateOutputs(m.getDeclaringClass(), m, true); + c.replace("{" + out.newOutput + out.methodOutput + out.classOutput + out.argsOutput + " $_ = $proceed($$); " + out.returnOutput + "}"); + } + } catch (NotFoundException e) { + e.printStackTrace(); } } }); - String newOutput = ""; - String methodOutput = ""; - String classOutput = ""; - String argsOutput = ""; - String returnOutput = ""; + // ���\�b�h�p�̏o�͕��𐶐����� + Outputs outputs = generateOutputs(cc, m, false); - String delimiter = "tracer.MyPrintStream.println(\"Args:\" + "; - CtClass parameterClasses[] = m.getParameterTypes(); - int p = 0; - for (CtClass c : parameterClasses) { - if (!c.isPrimitive()) { - argsOutput += delimiter + "$args[" + p + "].getClass().getName() + " + "\":\" + System.identityHashCode($" + (p + 1) + ")"; - } else { - argsOutput += delimiter + "$args[" + p + "].getClass().getName() + " + "\":\" + $" + (p + 1); - } - p++; - delimiter = " + \":\" + "; - } - if (p > 0) { - argsOutput += " + " + lineAndThread + ");"; - } + // ���\�b�h�̎��s�O��ɏo�͕���}������ + m.insertBefore("{" + outputs.newOutput + outputs.methodOutput + outputs.classOutput + outputs.argsOutput + "}"); + m.insertAfter("{" + outputs.returnOutput + "}"); - String accessor = ""; - if ((m.getModifiers() & Modifier.PUBLIC) != 0) { - accessor = "public "; - } else if ((m.getModifiers() & Modifier.PRIVATE) != 0) { - accessor = "private "; - } else if ((m.getModifiers() & Modifier.PROTECTED) != 0) { - accessor = "protected "; - } - String longName = null; - if ((m.getModifiers() & Modifier.STATIC) != 0) { - // static���\�b�h�̏ꍇ - longName = accessor + "static " + m.getLongName(); - methodOutput = "tracer.MyPrintStream.println(\"Method " + declaredClassName + "," + longName - + ":\" + 0 + " + line + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; - classOutput = "tracer.MyPrintStream.println(\"Class " + declaredClassName + ":\" + 0 + " + lineAndThread + ");"; - } else if (m instanceof CtConstructor) { - // �R���X�g���N�^�̏ꍇ - longName = accessor + m.getLongName(); - newOutput = "tracer.MyPrintStream.println(\"New " + declaredClassName + ":\" + 0 + " + lineAndThread + ");"; - methodOutput = "tracer.MyPrintStream.println(\"Method " + declaredClassName + "," + longName - + ":\" + 0 + " + line + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; - classOutput = "tracer.MyPrintStream.println(\"Class " + declaredClassName + ":\" + 0 + " + lineAndThread + ");"; - } else { - // �ʏ�̃��\�b�h�̏ꍇ - longName = accessor + ((CtMethod)m).getReturnType().getName() + " " + m.getLongName(); - methodOutput = "tracer.MyPrintStream.println(\"Method \" + this.getClass().getName() + \"," + longName - + ":\" + System.identityHashCode(this) + " + line + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; - classOutput = "tracer.MyPrintStream.println(\"Class \" + this.getClass().getName() + \":\" + System.identityHashCode(this) + " + lineAndThread + ");"; - } - - String shortName = null; - if ((m.getModifiers() & Modifier.STATIC) != 0) { - // static���\�b�h�̏ꍇ - shortName = cc.getSimpleName() + "." + m.getName() + "()"; - returnOutput = "if ($_ != null) {" + - "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):\" + $_.getClass().getName() + \":\" + System.identityHashCode($_) + \":\");" + - "} else {" + - "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):void:0:\");" + - "} " + - "tracer.MyPrintStream.println(\"0\" + " + lineAndThread + ");"; - } else if (m instanceof CtConstructor) { - // �R���X�g���N�^�̏ꍇ - shortName = m.getName() + "()"; - returnOutput = "tracer.MyPrintStream.print(\"Return initialization(" + shortName + "):" + declaredClassName + ":\" + System.identityHashCode($0) + \":\");" + - "tracer.MyPrintStream.println(\"\" + System.identityHashCode($0) + " + lineAndThread + ");"; - } else { - // �ʏ�̃��\�b�h�̏ꍇ - shortName = cc.getSimpleName() + "." + m.getName() + "()"; - returnOutput = "if ($_ != null) {" + - "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):\" + $_.getClass().getName() + \":\" + System.identityHashCode($_) + \":\");" + - "} else {" + - "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):void:0:\");" + - "} " + - "tracer.MyPrintStream.println(\"\" + System.identityHashCode(this) + " + lineAndThread + ");"; - } - - - m.insertBefore("{" + newOutput + methodOutput + classOutput + argsOutput + "}"); - m.insertAfter("{" + returnOutput + "}"); // CodeConverter conv = new CodeConverter(); // conv.replaceArrayAccess(cc, new // ArrayAccessReplacementMethodNames() { @@ -312,4 +268,137 @@ // }); } + private static Outputs generateOutputs(CtClass cls, CtBehavior m, boolean isCallerSideInstrumentation) throws NotFoundException { + Outputs outputs = new Outputs(); + String declaredClassName = cls.getName(); + String delimiter = "tracer.MyPrintStream.println(\"Args:\" + "; + CtClass parameterClasses[] = m.getParameterTypes(); + int p = 0; + for (CtClass c : parameterClasses) { + if (!c.isPrimitive()) { + outputs.argsOutput += delimiter + "$args[" + p + "].getClass().getName() + " + "\":\" + System.identityHashCode($" + (p + 1) + ")"; + } else { + outputs.argsOutput += delimiter + "$args[" + p + "].getClass().getName() + " + "\":\" + $" + (p + 1); + } + p++; + delimiter = " + \":\" + "; + } + if (p > 0) { + outputs.argsOutput += " + " + LINE_AND_THREAD + ");"; + } + + String accessor = ""; + if ((m.getModifiers() & Modifier.PUBLIC) != 0) { + accessor = "public "; + } else if ((m.getModifiers() & Modifier.PRIVATE) != 0) { + accessor = "private "; + } else if ((m.getModifiers() & Modifier.PROTECTED) != 0) { + accessor = "protected "; + } + String longName = null; + if ((m.getModifiers() & Modifier.STATIC) != 0) { + // static���\�b�h�̏ꍇ + longName = accessor + "static " + m.getLongName().replace('$', '.'); // AspectJ�ł̓��\�b�h�V�O�j�`�����ł͖����N���X�̓h�b�g�ŋ�؂��� + outputs.methodOutput = "tracer.MyPrintStream.println(\"Method " + declaredClassName + "," + longName + + ":\" + 0 + " + LINE + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; + outputs.classOutput = "tracer.MyPrintStream.println(\"Class " + declaredClassName + ":\" + 0 + " + LINE_AND_THREAD + ");"; + } else if (m instanceof CtConstructor) { + // �R���X�g���N�^�̏ꍇ + longName = accessor + m.getLongName().replace('$', '.'); // AspectJ�ł̓��\�b�h�V�O�j�`�����ł͖����N���X�̓h�b�g�ŋ�؂��� + outputs.newOutput = "tracer.MyPrintStream.println(\"New " + declaredClassName + ":\" + 0 + " + LINE_AND_THREAD + ");"; + outputs.methodOutput = "tracer.MyPrintStream.println(\"Method " + declaredClassName + "," + longName + + ":\" + 0 + " + LINE + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; + outputs.classOutput = "tracer.MyPrintStream.println(\"Class " + declaredClassName + ":\" + 0 + " + LINE_AND_THREAD + ");"; + } else { + // �ʏ�̃��\�b�h�̏ꍇ + longName = accessor + ((CtMethod)m).getReturnType().getName() + " " + m.getLongName().replace('$', '.'); // AspectJ�ł̓��\�b�h�V�O�j�`�����ł͖����N���X�̓h�b�g�ŋ�؂��� + if (!isCallerSideInstrumentation) { + // �Ăяo����ɖ��ߍ��ޏꍇ(�ʏ�) + outputs.methodOutput = "tracer.MyPrintStream.println(\"Method \" + this.getClass().getName() + \"," + longName + + ":\" + System.identityHashCode(this) + " + LINE + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; + outputs.classOutput = "tracer.MyPrintStream.println(\"Class \" + this.getClass().getName() + \":\" + System.identityHashCode(this) + " + LINE_AND_THREAD + ");"; + } else { + // �ďo�����ɖ��ߍ��ޏꍇ(�W���N���X�̌ďo��) + outputs.methodOutput = "tracer.MyPrintStream.println(\"Method \" + $0.getClass().getName() + \"," + longName + + ":\" + System.identityHashCode($0) + " + LINE + " + System.nanoTime() + \":ThreadNo \" + Thread.currentThread().getId());"; + outputs.classOutput = "tracer.MyPrintStream.println(\"Class \" + $0.getClass().getName() + \":\" + System.identityHashCode($0) + " + LINE_AND_THREAD + ");"; + } + } + + String shortName = null; + if ((m.getModifiers() & Modifier.STATIC) != 0) { + // static���\�b�h�̏ꍇ + shortName = cls.getSimpleName().replace('$', '.') + "." + m.getName() + "()"; // AspectJ�ł̓��\�b�h�V�O�j�`�����ł͖����N���X�̓h�b�g�ŋ�؂��� + String invocationType = null; + if (!isCallerSideInstrumentation) { + // �Ăяo����ɖ��ߍ��ޏꍇ(�ʏ�) + invocationType = "execution"; + } else { + // �ďo�����ɖ��ߍ��ޏꍇ(�W���N���X�̌ďo��) + invocationType = "call"; + } + if (!((CtMethod)m).getReturnType().isPrimitive() || ((CtMethod)m).getReturnType() == CtClass.voidType) { + outputs.returnOutput = "if ($_ != null) {" + + "tracer.MyPrintStream.print(\"Return " + invocationType + "(" + shortName + "):\" + $_.getClass().getName() + \":\" + System.identityHashCode($_) + \":\");" + + "} else {" + + "tracer.MyPrintStream.print(\"Return " + invocationType + "(" + shortName + "):void:0:\");" + + "} " + + "tracer.MyPrintStream.println(\"0\" + " + LINE_AND_THREAD + ");"; + } else { + outputs.returnOutput = "tracer.MyPrintStream.print(\"Return " + invocationType + "(" + shortName + "):" + ((CtMethod)m).getReturnType().getName() + ":\" + $_ + \":\");" + + "tracer.MyPrintStream.println(\"0\" + " + LINE_AND_THREAD + ");"; + } + } else if (m instanceof CtConstructor) { + // �R���X�g���N�^�̏ꍇ + shortName = m.getName().replace('$', '.') + "()"; // AspectJ�ł̓��\�b�h�V�O�j�`�����ł͖����N���X�̓h�b�g�ŋ�؂��� + if (!isCallerSideInstrumentation) { + // �Ăяo����ɖ��ߍ��ޏꍇ(�ʏ�) + outputs.returnOutput = "tracer.MyPrintStream.print(\"Return initialization(" + shortName + "):" + declaredClassName + ":\" + System.identityHashCode($0) + \":\");" + + "tracer.MyPrintStream.println(\"\" + System.identityHashCode($0) + " + LINE_AND_THREAD + ");"; + } else { + // �ďo�����ɖ��ߍ��ޏꍇ(�W���N���X�̌ďo��) + outputs.returnOutput = "tracer.MyPrintStream.print(\"Return call(" + shortName + "):" + declaredClassName + ":\" + System.identityHashCode($_) + \":\");" + + "tracer.MyPrintStream.println(\"\" + System.identityHashCode($_) + " + LINE_AND_THREAD + ");"; + } + } else { + // �ʏ�̃��\�b�h�̏ꍇ + shortName = cls.getSimpleName().replace('$', '.') + "." + m.getName() + "()"; // AspectJ�ł̓��\�b�h�V�O�j�`�����ł͖����N���X�̓h�b�g�ŋ�؂��� + if (!isCallerSideInstrumentation) { + // �Ăяo����ɖ��ߍ��ޏꍇ(�ʏ�) + if (!((CtMethod)m).getReturnType().isPrimitive() || ((CtMethod)m).getReturnType() == CtClass.voidType) { + outputs.returnOutput = "if ($_ != null) {" + + "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):\" + $_.getClass().getName() + \":\" + System.identityHashCode($_) + \":\");" + + "} else {" + + "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):void:0:\");" + + "} " + + "tracer.MyPrintStream.println(\"\" + System.identityHashCode(this) + " + LINE_AND_THREAD + ");"; + } else { + outputs.returnOutput = "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):" + ((CtMethod)m).getReturnType().getName() + ":\" + $_ + \":\");" + + "tracer.MyPrintStream.println(\"\" + System.identityHashCode(this) + " + LINE_AND_THREAD + ");"; + } + } else { + // �ďo�����ɖ��ߍ��ޏꍇ(�W���N���X�̌ďo��) + if (!((CtMethod)m).getReturnType().isPrimitive() || ((CtMethod)m).getReturnType() == CtClass.voidType) { + outputs.returnOutput = "if ($_ != null) {" + + "tracer.MyPrintStream.print(\"Return call(" + shortName + "):\" + $_.getClass().getName() + \":\" + System.identityHashCode($_) + \":\");" + + "} else {" + + "tracer.MyPrintStream.print(\"Return call(" + shortName + "):void:0:\");" + + "} " + + "tracer.MyPrintStream.println(\"\" + System.identityHashCode($0) + " + LINE_AND_THREAD + ");"; + } else { + outputs.returnOutput = "tracer.MyPrintStream.print(\"Return execution(" + shortName + "):" + ((CtMethod)m).getReturnType().getName() + ":\" + $_ + \":\");" + + "tracer.MyPrintStream.println(\"\" + System.identityHashCode($0) + " + LINE_AND_THREAD + ");"; + } + } + } + return outputs; + } + + private static class Outputs { + String newOutput = ""; + String methodOutput = ""; + String classOutput = ""; + String argsOutput = ""; + String returnOutput = ""; + } }