Newer
Older
org.ntlab.reverseDebugger / org.ntlab.reverseDebugger / src / org / ntlab / reverseDebugger / SeedAliases.java
package org.ntlab.reverseDebugger;

import java.util.ArrayList;
import java.util.List;

import org.ntlab.onlineAccessor.JDIDebuggingVirtualMachine;
import org.ntlab.onlineAccessor.JDIInstanceMethodCaller;
import org.ntlab.onlineAccessor.NotDebuggedException;
import org.ntlab.onlineAccessor.NotExecutedException;
import org.ntlab.onlineAccessor.NotSuspendedException;
import org.ntlab.reverseDebugger.analyzerProvider.ReverseDebuggerLaunchConfiguration;

import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.LongValue;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.StringReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;

@SuppressWarnings("restriction")
public class SeedAliases {
	private JDIInstanceMethodCaller debuggingMethodExecution = null;
	private List<JDIInstanceMethodCaller> seedAliases = new ArrayList<>();
	private static final String TRACER = "org.ntlab.traceAnalysisPlatform.tracer.trace";

	public SeedAliases() {
		initSeedAliases();
	}
	
	public JDIInstanceMethodCaller getDebuggingMethodExecution() {
		return debuggingMethodExecution;
	}
	
	public int getDebuggingLineNo() {
		try {
			ThreadReference thread = debuggingMethodExecution.getThread();
			return thread.frame(0).location().lineNumber();
		} catch (IncompatibleThreadStateException e) {
			throw new RuntimeException(e);
		}
	}
	
	public List<JDIInstanceMethodCaller> getSeedAliases() {
		return seedAliases;
	}
	
	public void reset() {
		seedAliases.clear();
	}
	
	public void initSeedAliases() {
		try {
			VirtualMachine vm = JDIDebuggingVirtualMachine.getDebuggineVirtualMachine();
			List<ThreadReference> allThreads = vm.allThreads();
			for (int i = 0; i < allThreads.size(); i++) {
				ThreadReference thread = allThreads.get(i);
				if (thread.isSuspended() && !(thread.name().equals("OnlineAnalysisThread"))) {
					createSeedAliases(vm, thread);
				}
			}			
		} catch (NotExecutedException | NotSuspendedException | NotDebuggedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 現在デバッガで止まっている地点でのメソッド実行中の全シードエイリアス一覧をセットする
	 * @param vm
	 * @param thread
	 */
	private void createSeedAliases(VirtualMachine vm, ThreadReference thread) {
		JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, thread);
		try {
			// threadIdの取得とStringReference型への変換
//			Value threadIdValue = mc.changeReceiver(thread).callInstanceMethod("getId");
			Value threadIdValue = vm.mirrorOf(mc.getThreadId());
			StringReference threadId =  vm.mirrorOf(String.valueOf(((LongValue)threadIdValue).value()));

			// threadIdに対応するThreadInstanceを取得
			ObjectReference threadInstance = (ObjectReference)mc.callStaticMethod(TRACER, "TraceJSON", "getThreadInstance", threadId);
			Value methodExecution = mc.changeReceiver(threadInstance).callInstanceMethod("getCurrentMethodExecution");
			debuggingMethodExecution = new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution);
			findAllSeedAlias(vm, thread, methodExecution);					
		} catch (InvalidTypeException | ClassNotLoadedException
				| InvocationException | IncompatibleThreadStateException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 渡されたエイリアスが示しているメソッド実行中の全シードエイリアスの一覧をセットする
	 * @param alias
	 */
	public void createSeedAliasesByAlias(JDIInstanceMethodCaller alias) {
		VirtualMachine vm = alias.getVm();
		ThreadReference thread = alias.getThread();
		try {
			Value methodExecution = alias.callInstanceMethod("getMethodExecution");
			findAllSeedAlias(vm, thread, methodExecution);
		} catch (InvalidTypeException | ClassNotLoadedException
				| InvocationException | IncompatibleThreadStateException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 渡されたメソッド実行中の全シードエイリアスの一覧をセットする
	 * @param methodExecution
	 */
	public void createSeedAliasesByMethodExecution(JDIInstanceMethodCaller methodExecution) {
		try {
			findAllSeedAlias(methodExecution.getVm(), methodExecution.getThread(), methodExecution.getReceiver());
		} catch (InvalidTypeException | ClassNotLoadedException
				| InvocationException | IncompatibleThreadStateException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 渡されたメソッド実行中の全シードエイリアスの一覧を, 実際にtraceCollector側と通信して取得しセットする
	 * @param vm
	 * @param thread
	 * @param methodExecution
	 */
	private void findAllSeedAlias(VirtualMachine vm, ThreadReference thread, Value methodExecution) throws InvalidTypeException, 
			ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
		JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null);
		seedAliases.clear();
		ObjectReference seedAliasList = (ObjectReference)mc.callStaticMethod(ReverseDebuggerLaunchConfiguration.ANALYZER_PACKAGE, ReverseDebuggerLaunchConfiguration.ANALYZER_CLASS, "findAllSeedAliasesStatic", methodExecution);
		int seedAliasListSize = ((IntegerValue)mc.changeReceiver(seedAliasList).callInstanceMethod("size")).value();
		for (int i = 0; i < seedAliasListSize; i++) {
			ObjectReference seedAlias = (ObjectReference)mc.changeReceiver(seedAliasList).callInstanceMethod("get", vm.mirrorOf(i));
			seedAliases.add(new JDIInstanceMethodCaller(vm, thread, seedAlias));			
		}
	}
}