diff --git a/org.ntlab.reverseDebugger/.classpath b/org.ntlab.reverseDebugger/.classpath
new file mode 100644
index 0000000..b1dabee
--- /dev/null
+++ b/org.ntlab.reverseDebugger/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/org.ntlab.reverseDebugger/.project b/org.ntlab.reverseDebugger/.project
new file mode 100644
index 0000000..68e238d
--- /dev/null
+++ b/org.ntlab.reverseDebugger/.project
@@ -0,0 +1,28 @@
+
+
+ org.ntlab.reverseDebugger
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs b/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..11f6e46
--- /dev/null
+++ b/org.ntlab.reverseDebugger/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF b/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..d51ce53
--- /dev/null
+++ b/org.ntlab.reverseDebugger/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: DebuggingControl
+Bundle-SymbolicName: org.ntlab.reverseDebugger2;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.ntlab.debuggingControl.Activator
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.debug.core,
+ org.eclipse.jdt.debug,
+ org.eclipse.jdt.core;bundle-version="3.10.2",
+ org.eclipse.jdt.ui;bundle-version="3.10.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
diff --git a/org.ntlab.reverseDebugger/bin/.gitignore b/org.ntlab.reverseDebugger/bin/.gitignore
new file mode 100644
index 0000000..cf1db2e
--- /dev/null
+++ b/org.ntlab.reverseDebugger/bin/.gitignore
@@ -0,0 +1 @@
+/org/
diff --git a/org.ntlab.reverseDebugger/build.properties b/org.ntlab.reverseDebugger/build.properties
new file mode 100644
index 0000000..6f20375
--- /dev/null
+++ b/org.ntlab.reverseDebugger/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/org.ntlab.reverseDebugger/plugin.xml b/org.ntlab.reverseDebugger/plugin.xml
new file mode 100644
index 0000000..c7729d6
--- /dev/null
+++ b/org.ntlab.reverseDebugger/plugin.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/Activator.java b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/Activator.java
new file mode 100644
index 0000000..e6910b9
--- /dev/null
+++ b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/Activator.java
@@ -0,0 +1,50 @@
+package org.ntlab.debuggingControl;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.ntlab.helloWorld"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/DebuggingControlAction.java b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/DebuggingControlAction.java
new file mode 100644
index 0000000..cc7f4cf
--- /dev/null
+++ b/org.ntlab.reverseDebugger/src/org/ntlab/debuggingControl/DebuggingControlAction.java
@@ -0,0 +1,738 @@
+package org.ntlab.debuggingControl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.internal.core.LaunchManager;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.PartInitException;
+
+import com.sun.jdi.AbsentInformationException;
+import com.sun.jdi.BooleanValue;
+import com.sun.jdi.ByteValue;
+import com.sun.jdi.CharValue;
+import com.sun.jdi.ClassNotLoadedException;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.DoubleValue;
+import com.sun.jdi.Field;
+import com.sun.jdi.FloatValue;
+import com.sun.jdi.IncompatibleThreadStateException;
+import com.sun.jdi.IntegerValue;
+import com.sun.jdi.InvalidTypeException;
+import com.sun.jdi.InvocationException;
+import com.sun.jdi.LocalVariable;
+import com.sun.jdi.Location;
+import com.sun.jdi.LongValue;
+import com.sun.jdi.Method;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.ShortValue;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.StringReference;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.Value;
+import com.sun.jdi.VirtualMachine;
+
+public class DebuggingControlAction implements IWorkbenchWindowActionDelegate {
+
+ @Override
+ public void run(IAction arg0) {
+ // TODO Auto-generated method stub
+ LaunchManager lm = (LaunchManager)DebugPlugin.getDefault().getLaunchManager();
+
+ ILaunch[] launches = lm.getLaunches();
+ if (launches.length == 0) {
+ MessageDialog.openInformation(null, null, "��xJava�v���O���������s����������");
+ } else {
+ ILaunch debugLaunch = null;
+ for (int i = 0; i < launches.length; i++) {
+ System.out.print(launches[i].getLaunchConfiguration().getName() + ":");
+ System.out.print(launches[i].getDebugTarget());
+ if (launches[i].getDebugTarget() != null) {
+ debugLaunch = launches[i];
+ break;
+ }
+ }
+ if (debugLaunch != null) {
+ JDIDebugTarget debugTarget = ((JDIDebugTarget)debugLaunch.getDebugTarget());
+ VirtualMachine vm = debugTarget.getVM();
+ if (vm != null) {
+ // �f�o�b�O���s���̏ꍇ
+ List allThreads = vm.allThreads();
+ for (int i = 0; i < allThreads.size(); i++) {
+ ThreadReference thread = allThreads.get(i);
+ if (thread.isSuspended()) {
+ try {
+ // ��~���Ă���X���b�h���ǂ̃N���X�i�ǂ̃��\�b�h�j�̉��s�ڂŒ�~���Ă���̂���\������
+ List frames = thread.frames(); // ��~�X���b�h���̑S�X�^�b�N�t���[��
+ StackFrame topFrame = frames.get(0);
+ Location location = topFrame.location(); // �X�^�b�N�g�b�v�ɂ���t���[��(�u���[�N�|�C���g�Œ�~��)
+ MessageDialog.openInformation(null, null, "Thread [" + thread.name() + "] \n"
+ + location.method().declaringType().name() + "." + location.method().name() + location.method().signature() + " line: "
+ + location.lineNumber());
+ System.out.println();
+ callCollectorMethods(vm, thread); // traceCollector�̃��\�b�h�Ăяo���֘A
+ System.out.println();
+ } catch (InvalidTypeException
+ | ClassNotLoadedException
+ | InvocationException e) {
+ e.printStackTrace();
+ } catch (IncompatibleThreadStateException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } else {
+ MessageDialog.openInformation(null, null, "Java�v���O�������f�o�b�O���s���̒�~��Ԃɂ��Ă�������");
+ }
+ } else {
+ MessageDialog.openInformation(null, null, "Java�v���O�������f�o�b�O���s����������");
+ }
+ }
+ }
+
+ @Override
+ public void selectionChanged(IAction arg0, ISelection arg1) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void dispose() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void init(IWorkbenchWindow arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * traceCollector�̃��\�b�h���Ă�
+ * @param vm
+ * @param thread
+ */
+ private void callCollectorMethods(VirtualMachine vm, ThreadReference thread) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ String packageName = "org.ntlab.traceCollector.tracer.trace";
+ String className;
+ String methodName;
+
+ // threadId�̎擾��StringReference�^�ւ̕ϊ�
+ methodName = "getId";
+ Value threadIdValue = callInstanceMethod(vm, thread, methodName, thread);
+ StringReference threadId = vm.mirrorOf(String.valueOf(((LongValue)threadIdValue).value()));
+ System.out.print("threadId = " + threadId); // �擾����ThreadId�̊m�F�p
+
+ // threadId�ɑΉ�����ThreadInstance���擾
+ className = "TraceJSON";
+ methodName = "getThreadInstanceForDebuggingControl";
+ Value threadInstance = callStaticMethod(vm, thread, packageName, className, methodName, threadId);
+
+ // threadInstance�̌Ăяo���X�^�b�N��̃��\�b�h�ɂ��Ă̊e��f�[�^���擾���ĕ\������
+// printStackData(vm, thread, threadInstance);
+
+ // threadInstance�̃��\�b�h�Ăяo���̑S���\�b�h�ɂ��Ă̊e��f�[�^���擾���ĕ\������
+ printCallTreeDataFromRoot(vm, thread, threadInstance);
+ }
+
+ /**
+ * �����œn����threadInstance�̌Ăяo���X�^�b�N��̃��\�b�h�ɂ��Ă̊e��f�[�^���擾���ĕ\������
+ * @param vm
+ * @param thread
+ * @param threadInstance
+ */
+ private void printStackData(VirtualMachine vm, ThreadReference thread, Value threadInstance) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // ThreadInstance������curMethodExecution���擾
+ String methodName = "getCurrentMethodExecution";
+ Value methodExecution = callInstanceMethod(vm, thread, methodName, (ObjectReference)threadInstance);
+ Value child = null;
+
+ // curMethodExetuion�̃V�O�l�`�����擾���A���̌Ăяo�����̃��\�b�h�ɂ��Ă����l�̏������J��Ԃ�
+ while (methodExecution != null) {
+ Value lineNo = (child != null) ? getMethodExecutionLineNo(vm, thread, methodExecution, child)
+ : vm.mirrorOf(thread.frame(0).location().lineNumber()); // child == null �̂Ƃ�(=�X�^�b�N�̃g�b�v�̂Ƃ�)�́A���m��lineNo��JDI���̃��\�b�h��p���Ď擾����
+
+ // �f�[�^�̎擾�ƕ\���֘A
+ String indent = " ";
+ Value methodSignature = getMethodExecutionSignature(vm, thread, methodExecution);
+ printValue("", "", methodSignature, true);
+ printValue(indent, "lineNo = ", lineNo, true);
+ System.out.println();
+ IType type = findIType(vm, thread, methodExecution);
+ IMethod method = findIMethod(vm, thread, type, methodExecution);
+ openSrcFileOfIMethod(type, method);
+ printAllIdAndType(vm, thread, methodExecution, method, indent);
+
+ // curMethodExecution�̌Ăяo�����\�b�h���擾 (MethodExecution)
+ child = methodExecution;
+ methodName = "getParent";
+ methodExecution = callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ }
+ }
+
+ /**
+ * �����œn����threadInstance�̌Ăяo���̃��\�b�h�ɂ��Ă̊e��f�[�^���擾���ĕ\������
+ * �Ăяo���̃��\�b�h�͊ethreadInstance�ł�Root���珇�ԂɎ擾
+ * @param vm
+ * @param thread
+ * @param threadInstance
+ */
+ private void printCallTreeDataFromRoot(VirtualMachine vm, ThreadReference thread, Value threadInstance) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // ThreadInstance������root��MethodExecution���擾(ArrayList)
+ String methodName = "getRoot";
+ Value methodExecutions = callInstanceMethod(vm, thread, methodName, (ObjectReference)threadInstance);
+ printCallTreeData(vm, thread, null, methodExecutions, "");
+ }
+
+ /**
+ * �����œn����methodExecution���X�g�������\�b�h���N�_�Ƃ��āA�Ăяo����[���D��T����
+ * �s���������ŒT�����āA���\�b�h�Ƃ��̊e��f�[�^���擾���ĕ\������
+ * @param vm
+ * @param thread
+ * @param parent
+ * @param methodExecutions
+ * @param indent
+ */
+ private void printCallTreeData(VirtualMachine vm, ThreadReference thread, Value parent, Value methodExecutions, String indent) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ if (methodExecutions == null) {
+ return;
+ }
+ String methodName = "size";
+ final int METHOD_EXECUTION_SIZE = ((IntegerValue)callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecutions)).value();
+ if (METHOD_EXECUTION_SIZE == 0) {
+ return;
+ }
+
+ final String DEEP_SPACE_INDENT = indent.replace("-", " ") + " "; // ���\�b�h�V�O�l�`���ȊO�ł̕\���p
+ for (int i = 0; i < METHOD_EXECUTION_SIZE; i++) {
+ IntegerValue index = vm.mirrorOf(i);
+ methodName = "get";
+ Value methodExecution = callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecutions, index);
+ Value lineNo = (parent != null) ? getMethodExecutionLineNo(vm, thread, parent, methodExecution) : vm.mirrorOf(0);
+
+ // �f�[�^�̎擾�ƕ\���֘A
+ Value methodSignature = getMethodExecutionSignature(vm, thread, methodExecution);
+ printValue(indent, "", methodSignature, true);
+ printValue(DEEP_SPACE_INDENT, "lineNoCalledByParent = ", lineNo, true);
+ System.out.println();
+ IType type = findIType(vm, thread, methodExecution);
+ IMethod method = findIMethod(vm, thread, type, methodExecution);
+ openSrcFileOfIMethod(type, method);
+ printAllIdAndType(vm, thread, methodExecution, method, DEEP_SPACE_INDENT);
+
+ // ���\�b�h�Ăяo���ɂ����Ă̎q���\�b�h�ɂ��Ă����l�̏������ċA�I�ɍs��
+ methodName = "getChildren";
+ Value children = callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ printCallTreeData(vm, thread, methodExecution, children, (indent + "--------"));
+ }
+ }
+
+ /**
+ * this�≼������ID��Type �y�� ����炪���t�B�[���h��ID��Type��S�ĕ\������
+ * @param vm
+ * @param thread
+ * @param methodExecution
+ * @param method
+ * @param indent
+ */
+ private void printAllIdAndType(VirtualMachine vm, ThreadReference thread, Value methodExecution, IMethod method, String indent) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // this��ID��Type���擾���ĕ\��
+ Value thisId = getMethodExecutionThisId(vm, thread, methodExecution);
+ printValue(indent, "this id = ", thisId, true);
+ Value thisType = getMethodExecutionThisType(vm, thread, methodExecution);
+ printValue("", " type = ", thisType, false);
+
+ // this�̎��t�B�[���h��ID��Type��\�� (�Ăяo����ōċA)
+ System.out.println();
+ printFieldIdAndType(vm, thread, thisType, thisId, (indent + " "));
+
+ // ������ID��Type �y�т��̈��������t�B�[���h��ID��Type��\�� (�Ăяo����ōċA)
+ System.out.println();
+ printArgsIdAndType(vm, thread, methodExecution, method, indent);
+ }
+
+ private Value getMethodExecutionSignature(VirtualMachine vm, ThreadReference thread, Value methodExecution) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // curMethodExecution�̃V�O�l�`�����擾(String)
+ String methodName = "getSignature";
+ return callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ }
+
+ private Value getMethodExecutionThisType(VirtualMachine vm, ThreadReference thread, Value methodExecution) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // thisClassName���擾(String)
+ String methodName = "getThisClassName";
+ return callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ }
+
+ private Value getMethodExecutionThisId(VirtualMachine vm, ThreadReference thread, Value methodExecution) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // thisObjId���擾(String)
+ String methodName = "getThisObjId";
+ return callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ }
+
+ private Value getMethodExecutionLineNo(VirtualMachine vm, ThreadReference thread, Value methodExecution, Value child) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // methodExecution��child���Ăяo�����ꏊ��lineNo���擾(IntegerValue)
+ String methodName = "getMethodInvocation";
+ ObjectReference methodInvocation = (ObjectReference)callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution, child);
+ if (methodInvocation != null) {
+ methodName = "getLineNo";
+ return callInstanceMethod(vm, thread, methodName, methodInvocation);
+ }
+ return null;
+ }
+
+ private void printFieldIdAndType(VirtualMachine vm, ThreadReference thread, Value thisClassName, Value thisObjId, String indent) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ String packageName = "org.ntlab.traceCollector.tracer.trace";
+ String className = "TraceJSON";
+ String methodName;
+
+ // �t�B�[���h��ID��Type���擾���ĕ\��
+ List classes = vm.classesByName(((StringReference)thisClassName).value());
+ ClassType type = (ClassType)classes.get(0);
+ for (Field field : type.allFields()) {
+ if (field.isStatic()) {
+ continue; // static�t�B�[���h�͔�� (��낤�Ƃ��Ă��AID��Type�����Ȃ�)
+ }
+ String fieldName = field.declaringType().name() + "." + field.name(); // ���S���薼
+ System.out.print(indent + fieldName);
+
+ // ���̃t�B�[���h�ɂ��Ă̍ŐV�̍X�V�����擾(FieldUpdate)
+ methodName = "getRecentlyFieldUpdateForDebuggingControl";
+ ObjectReference fieldUpdate = (ObjectReference)callStaticMethod(vm, thread, packageName, className, methodName, thisObjId, vm.mirrorOf(fieldName), thread);
+ if (fieldUpdate == null) {
+ System.out.println(" id = null����!" + " type = null����!");
+ continue;
+ }
+
+ // �t�B�[���h��ID��Type���擾(String)
+ methodName = "getValueObjId";
+ Value fieldObjIdValue = callInstanceMethod(vm, thread, methodName, fieldUpdate);
+ printValue("", " id = ", fieldObjIdValue, false);
+ methodName = "getValueClassName";
+ Value fieldTypeValue = callInstanceMethod(vm, thread, methodName, fieldUpdate);
+ printValue("", " type = ", fieldTypeValue, false);
+
+ // �擾�����t�B�[���h���I�u�W�F�N�g��z��̏ꍇ�ɁA���̃I�u�W�F�N�g��z���t�B�[���h�ɂ��Ă̏������s��
+ System.out.println();
+ printDeepHierarchyField(vm, thread, fieldObjIdValue, fieldTypeValue, fieldName, (indent + " "));
+ }
+ }
+
+ /**
+ * �����œn�����t�B�[���h���Q�ƌ^�̏ꍇ��A�z��̏ꍇ�ɁA
+ * ���̎Q�ƌ^�I�u�W�F�N�g�������Ă���t�B�[���h��A�z��̊e�v�f�̃I�u�W�F�N�g�ɂ��āA
+ * ���ꂼ��ɑΉ��������\�b�h������ɌĂяo�� (���̃��\�b�h�ƑΉ����\�b�h�Ƃ̑��ݍċA)
+ * @param vm
+ * @param thread
+ * @param objIdValue
+ * @param typeValue
+ * @param fieldName
+ * @param indent
+ */
+ private void printDeepHierarchyField(VirtualMachine vm, ThreadReference thread, Value objIdValue, Value typeValue,
+ String fieldName, String indent) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // �t�B�[���h��ID��Type���Ȃ��ꍇ��AType(=ActualType)��"---"�̏ꍇ�͉������Ȃ�
+ if (objIdValue == null
+ || typeValue == null
+ || ((StringReference)objIdValue).value().isEmpty()
+ || ((StringReference)typeValue).value().isEmpty()) {
+ return;
+ }
+ final String NULL_ACTUAL_TYPE = "---"; // �t�B�[���h�ɑ��Ė����I��null����ꂽ�ꍇ��ActualType�̎擾������
+ String fieldType = ((StringReference)typeValue).value();
+ if (fieldType.equals(NULL_ACTUAL_TYPE)) {
+ return;
+ }
+
+ final String ARRAY_SIGNATURE_HEAD = "["; // �z��̃V�O�l�`���̐擪�́A�z��̎��������� [ ���A�Ȃ�
+ if (fieldType.startsWith(ARRAY_SIGNATURE_HEAD)) {
+ // �t�B�[���h��Type���z��^(�@[ �Ŏn�܂�@)�ꍇ (���̔z���e�v�f�ɂ��Ă���Ȃ�f�[�^�擾�������Ăяo��)
+ printArrayIdAndType(vm, thread, objIdValue, fieldName, indent);
+ } else {
+ String[] primitives = {"byte", "short", "int", "long", "float", "double", "char", "boolean"};
+ if (!Arrays.asList(primitives).contains(fieldType)) {
+ // �t�B�[���h��Type���Q�ƌ^(=�I�u�W�F�N�g)�̏ꍇ (���̃I�u�W�F�N�g�������Ă���t�B�[���h�ɂ��Ă���Ȃ�f�[�^�擾�������Ăяo��)
+ printFieldIdAndType(vm, thread, typeValue, objIdValue, indent);
+ }
+ }
+ }
+
+ private void printArrayIdAndType(VirtualMachine vm, ThreadReference thread, Value arrayObjId, String arrayName, String indent) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ String packageName = "org.ntlab.traceCollector.tracer.trace";
+ String className = "TraceJSON";
+ String methodName;
+
+ for (int i = 0;; i++){
+ // ���̔z��v�f�ɂ��Ă̍ŐV�̍X�V�����擾(ArrayUpdate)
+ methodName = "getRecentlyArrayUpdateForDebuggingControl";
+ IntegerValue index = vm.mirrorOf(i);
+ ObjectReference arrayUpdate = (ObjectReference)callStaticMethod(vm, thread, packageName, className, methodName, arrayObjId, index, thread);
+ if (arrayUpdate == null) {
+ // �z��̃T�C�Y���擾�ł��Ȃ����߁A�C���f�b�N�X���T�C�Y���߂̂Ƃ��Ɋm���ɔ���������@�Ƃ��ĉ�����
+ // �������A�z��v�f�̓r���ɖ���`���������ꍇ�ł��A�����Ă��܂��̂����_
+ break;
+ }
+ String arrayIndexName = arrayName + "[" + index.value() + "]";
+ System.out.print(indent + arrayIndexName);
+
+ // �z��v�f��ID��Type���擾(String)
+ methodName = "getValueObjectId";
+ Value valueObjId = callInstanceMethod(vm, thread, methodName, arrayUpdate);
+ printValue("", " id = ", valueObjId, false);
+ methodName = "getValueClassName";
+ Value valueType = callInstanceMethod(vm, thread, methodName, arrayUpdate);
+ printValue("", " type = ", valueType, false);
+
+ // �擾�����z��v�f���I�u�W�F�N�g��z��̏ꍇ�ɁA���̃I�u�W�F�N�g��z���t�B�[���h�ɂ��Ă̏������s��
+ System.out.println();
+ printDeepHierarchyField(vm, thread, valueObjId, valueType, arrayIndexName, (indent + " "));
+ }
+ }
+
+ private void printArgsIdAndType(VirtualMachine vm, ThreadReference thread, Value methodExecution, IMethod method, String indent) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ // methodExecution������arguments���擾(ArrayList)���A����arguments�̃T�C�Y���擾(int)
+ String methodName = "getArguments";
+ ObjectReference args = (ObjectReference)callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ methodName = "size";
+ final int ARGUMENTS_NUM = ((IntegerValue)callInstanceMethod(vm, thread, methodName, args)).value();
+ if (ARGUMENTS_NUM > 0) {
+ String[] argNames = getParameterNames(method); // ������IMethod���牼���������擾����
+ System.out.println(indent + "args");
+ for (int i = 0; i < ARGUMENTS_NUM; i++) {
+ String argName = (argNames.length == ARGUMENTS_NUM) ? argNames[i] : "arg" + i; // ���Ȃ��Ƃ������̌����s��v�̂Ƃ��͐����������������Ă��Ȃ�
+ methodName = "get";
+ ObjectReference arg = (ObjectReference)callInstanceMethod(vm, thread, methodName, args, vm.mirrorOf(i));
+ methodName = "getId";
+ Value argId = callInstanceMethod(vm, thread, methodName, arg);
+ methodName = "getActualType";
+ Value argType = callInstanceMethod(vm, thread, methodName, arg);
+ System.out.println(indent + argName + " id = " + ((StringReference)argId).value() + " type = " + ((StringReference)argType).value());
+ printDeepHierarchyField(vm, thread, argId, argType, argName, (indent + " "));
+ System.out.println();
+ }
+ }
+ }
+
+ private String[] getParameterNames(IMethod method) {
+ String[] argNames = new String[0];
+ if (method != null) {
+ try {
+ argNames = method.getParameterNames();
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+ }
+ return argNames;
+ }
+
+ /**
+ * �����œn����methodExecution����`����Ă���N���X�̃\�[�X�R�[�h��Ώ�Eclipse�̃G�f�B�^�ŊJ������
+ * @param vm
+ * @param thread
+ * @param methodExecution
+ */
+ private void openSrcFileOfMethodExecution(VirtualMachine vm, ThreadReference thread, Value methodExecution) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ IType type = findIType(vm, thread, methodExecution);
+ if (type != null) {
+ IMethod method = findIMethod(vm, thread, type, methodExecution);
+ if (method != null) {
+ openSrcFileOfIMethod(type, method);
+ }
+ }
+ }
+
+ /**
+ * �����œn����IType��IMethod�ɑΉ�����\�[�X�R�[�h��Ώ�Eclipse�̃G�f�B�^�ŊJ������
+ * @param type
+ * @param method
+ */
+ private void openSrcFileOfIMethod(IType type, IMethod method) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ openInJavaEditor(type, method);
+ }
+
+ private IType findIType(VirtualMachine vm, ThreadReference thread, Value methodExecution) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ String methodName = "getDeclaringClassName";
+ StringReference declaringClassName = (StringReference)callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ String projectPath = getLoaderPath(vm, thread, methodExecution, declaringClassName);
+ IType type = null;
+ if (projectPath != null) {
+ IJavaProject javaProject = findJavaProject(projectPath);
+ if (javaProject != null) {
+ StringReference methodSignature = (StringReference)getMethodExecutionSignature(vm, thread, methodExecution);
+ try {
+ type = javaProject.findType(declaringClassName.value());
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return type;
+ }
+
+ private String getLoaderPath(VirtualMachine vm, ThreadReference thread, Value methodExecution, StringReference declaringClassName) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ String packageName = "org.ntlab.traceCollector.tracer.trace";
+ String className = "TraceJSON";
+ String methodName;
+
+ methodName = "getClassInfo";
+ ObjectReference classInfo = (ObjectReference)callStaticMethod(vm, thread, packageName, className, methodName, declaringClassName);
+ if (classInfo == null) {
+ methodName = "getThisClassName";
+ declaringClassName = (StringReference)callInstanceMethod(vm, thread, methodName, (ObjectReference)methodExecution);
+ methodName = "getClassInfo";
+ classInfo = (ObjectReference)callStaticMethod(vm, thread, packageName, className, methodName, declaringClassName);
+ }
+ String loaderPath = null;
+ if (classInfo != null) {
+// // loaderPath���擾
+// methodName = "getLoaderPath";
+// loaderPath = ((StringReference)callInstanceMethod(vm, thread, methodName, classInfo)).value();
+
+ // �Ȃ���loaderPath���擾�ł��Ă��Ȃ����߁A���ۂɏo�͂����JSON�g���[�X���Q�l�ɂ���path����^���Ă݂�
+ methodName = "getPath";
+ String path = ((StringReference)callInstanceMethod(vm, thread, methodName, classInfo)).value();
+ String declaringClassNameString = declaringClassName.value().replace(".", "/");
+ loaderPath = path.substring(0, path.indexOf(declaringClassNameString)); // path����N���X�̊��S���薼�ȍ~��S�ĊO�������̂�projectPath�ɂ��Ă݂�
+ }
+ return loaderPath;
+ }
+
+ private IJavaProject findJavaProject(String projectPath) {
+ IJavaProject javaProject = null;
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IProject[] projects = root.getProjects();
+ for (IProject project: projects) {
+ if (checkProjectPath(project, projectPath)) {
+ javaProject = JavaCore.create(project);
+ break;
+ }
+ }
+ return javaProject;
+ }
+
+ private boolean checkProjectPath(IProject project, String projectPath) {
+ String projectLocation = project.getLocation().toString();
+ if (projectPath.startsWith(projectLocation)) {
+ String[] projectPathSplit = projectPath.split(projectLocation);
+ return (projectPathSplit[1].charAt(0) == '/'); // �v���W�F�N�g���̑O����v�ɂ�鑼�v���W�F�N�g�Ƃ̌딻��������
+ }
+ return false;
+ }
+
+ private void openInJavaEditor(IType type, IMethod method) {
+ try {
+ if (type != null && method != null) {
+ IEditorPart editor = JavaUI.openInEditor(type);
+ if (!type.isLocal() && !type.isMember()) {
+ JavaUI.revealInEditor(editor, (IJavaElement)method);
+ System.out.println("JavaUI.revealInEditor() ���Ăяo������!");
+ }
+ }
+ } catch (PartInitException | JavaModelException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private IMethod findIMethod(VirtualMachine vm, ThreadReference thread, IType type, Value methodExecution) throws InvalidTypeException,
+ ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ IMethod method = null;
+ if (type != null) {
+ StringReference methodSignature = (StringReference)getMethodExecutionSignature(vm, thread, methodExecution);
+ method = findIMethod(type, methodSignature.value());
+ }
+ return method;
+ }
+
+ private IMethod findIMethod(IType type, String methodSignature) {
+ try {
+ for (IMethod method: type.getMethods()) {
+ if (checkMethodSignature(type, method, methodSignature)) {
+ return method;
+ }
+ }
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private boolean checkMethodSignature(IType type, IMethod method, String methodSignature) {
+ String fqcn = type.getFullyQualifiedName();
+ try {
+ String jdiMethodSignature = (method.isConstructor()) ? (fqcn + "(") : (fqcn + "." + method.getElementName() + "(");
+ System.out.println(jdiMethodSignature);
+ if (methodSignature.contains(jdiMethodSignature)) {
+ // ������v���Ă����ꍇ�Ɍ���A�������X�g����������ł���v���邩�ǂ����� (�I�[�o�[���[�h�ɂ��딻��������)
+ jdiMethodSignature += String.join(",", parseFQCNParameters(type, method)) + ")"; // �S�����̃V�O�l�`�������S���薼�ɕϊ�����,�ŋ����������
+ System.out.println(jdiMethodSignature);
+ return methodSignature.contains(jdiMethodSignature);
+ }
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ /**
+ * IMethod����擾�ł���S�����̃V�O�l�`�������S���薼�ɒu�������Ċi�[�������X�g��Ԃ�
+ * @param type
+ * @param method
+ * @return
+ * @throws JavaModelException
+ */
+ private List parseFQCNParameters(IType type, IMethod method) throws JavaModelException {
+ List parameters = new ArrayList<>();
+ for (String parameterType : method.getParameterTypes()) {
+ String readableType = Signature.toString(parameterType); // �V�O�l�`���̕�������^���̕�����ɕϊ� (�z��͌���[]����)
+ String[] readableTypeSplit = {"", ""}; // �^����[]�̕����p
+ int firstBracketIndex = readableType.indexOf("[]");
+ final int NO_BRACKET_INDEX = -1;
+ if (firstBracketIndex == NO_BRACKET_INDEX) {
+ readableTypeSplit[0] = readableType; // �^��
+ } else {
+ readableTypeSplit[0] = readableType.substring(0, firstBracketIndex); // �^��
+ readableTypeSplit[1] = readableType.substring(firstBracketIndex); // �^���̌���[]�S��
+ }
+ String[][] resolveType = type.resolveType(readableTypeSplit[0]); // �p�b�P�[�W���ƃN���X���̑g�ݍ��킹���擾
+ if (resolveType != null) {
+ readableTypeSplit[0] = (resolveType[0][0] + "." + resolveType[0][1]); // ���S���薼
+ }
+ parameters.add(readableTypeSplit[0] + readableTypeSplit[1]);
+ }
+ return parameters;
+ }
+
+ /**
+ * �p�b�P�[�W���ƃN���X���ƃ��\�b�h���ƈ������w�肵�Ă��̃N���X���\�b�h���Ăяo��
+ * @param vm
+ * @param thread
+ * @param packageName �Ăт����������\�b�h������N���X�̃p�b�P�[�W�� (�N���X���ƌq���Ŋ��S���薼�ɂ��邽�߁A������ . ������)
+ * @param className �Ăяo���������\�b�h������N���X��
+ * @param methodName �Ăяo���������\�b�h�� (static)
+ * @param args �Ăяo���������\�b�h�ɓn������(Value �̃N���X�^�ʼnϒ�)
+ * @return �Ăяo�������\�b�h����̖߂�l(Value)
+ */
+ private Value callStaticMethod(VirtualMachine vm, ThreadReference thread, String packageName, String className, String methodName, Value... args)
+ throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ List classes = vm.classesByName(packageName + "." + className); // �N���X�� (���S���薼)
+ ClassType type = (ClassType)classes.get(0);
+ List methodsByName = type.methodsByName(methodName);
+ List argList = Arrays.asList(args); // ���\�b�h�ɓn�������̃��X�g
+ return type.invokeMethod(thread, methodsByName.get(0), argList, thread.INVOKE_SINGLE_THREADED); // �f�o�b�O���̃v���O�������̃��\�b�h���Ăяo��
+ }
+
+ /**
+ * ���\�b�h����ObjectReference�ƈ������w�肵�Ă��̃I�u�W�F�N�g�̃C���X�^���X���\�b�h���Ăяo��
+ * @param vm
+ * @param thread
+ * @param methodName �Ăяo���������\�b�h��
+ * @param obj receiver�̃C���X�^���X�ɑΉ�����ObjectReference
+ * @param args �Ăяo���������\�b�h�ɓn������(Value �̃N���X�^�ʼnϒ�)
+ * @return �Ăяo�������\�b�h����̖߂�l(Value)
+ */
+ private Value callInstanceMethod(VirtualMachine vm, ThreadReference thread, String methodName, ObjectReference obj, Value... args)
+ throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
+ ClassType type = (ClassType)obj.type();
+ List methodsByName = type.methodsByName(methodName);
+ List argList = Arrays.asList(args); // ���\�b�h�ɓn�������̃��X�g
+ return obj.invokeMethod(thread, methodsByName.get(0), argList, thread.INVOKE_SINGLE_THREADED); // �f�o�b�O���̃v���O�������̃��\�b�h���Ăяo��
+ }
+
+ /**
+ * �����œn���ꂽValue�N���X��\������
+ * (Value�N���X�̎q�N���X����Ή������{�^��String�^�����邱�Ƃ̊m�F�����˂Ă���)
+ * @param indent �C���f���g
+ * @param msg Value�̕\���O�ɓ���郁�b�Z�[�W
+ * @param value �\����������Value
+ * @param isNewLine ���̃��\�b�h�ɂ��\��������ۂɉ��s�����Ă���\�����邩
+ */
+ private void printValue(String indent, String msg, Value value, boolean isNewLine) {
+ System.out.print(((isNewLine) ? "\n" : "") + indent + msg);
+ printValue(value);
+ }
+
+ /**
+ * �����œn���ꂽValue�N���X��\������
+ * (Value�N���X�̎q�N���X����Ή������{�^��String�^�����邱�Ƃ̊m�F�����˂Ă���)
+ * @param value
+ */
+ private void printValue(Value value) {
+ if (value == null) {
+ System.out.print("null����!");
+ return;
+ }
+ if (value instanceof StringReference) {
+ String log = ((StringReference)value).value();
+ System.out.print(log);
+ } else if (value instanceof IntegerValue) {
+ int log = ((IntegerValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof LongValue) {
+ long log = ((LongValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof BooleanValue) {
+ boolean log = ((BooleanValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof DoubleValue) {
+ double log = ((DoubleValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof FloatValue) {
+ float log = ((FloatValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof ShortValue) {
+ short log = ((ShortValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof ByteValue) {
+ byte log = ((ByteValue)value).value();
+ System.out.print(log);
+ } else if (value instanceof CharValue) {
+ char log = ((CharValue)value).value();
+ System.out.print(log);
+ } else {
+ throw new IllegalArgumentException("value is not Primitive or String");
+ }
+ }
+}