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)); } } }