Newer
Older
MagnetRON / src / org / ntlab / trace / TraceJPDA.java
Aki Hongo on 3 Mar 2020 4 KB first commit
  1. package org.ntlab.trace;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. import java.util.HashSet;
  9. import java.util.Iterator;
  10. import java.util.Stack;
  11.  
  12. public class TraceJPDA {
  13. protected HashMap<String, ThreadInstanceJPDA> threads = new HashMap<String, ThreadInstanceJPDA>();
  14. /**
  15. * 指定したJSONトレースファイルを解読して Trace オブジェクトを生成する
  16. * @param traceFile トレースファイルのパス
  17. */
  18. public TraceJPDA(BufferedReader file) {
  19. try {
  20. readJPDA(file);
  21. file.close();
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. /**
  27. * 指定したJSONトレースファイルを解読して Trace オブジェクトを生成する
  28. * @param traceFile トレースファイルのパス
  29. */
  30. public TraceJPDA(String traceFile) {
  31. BufferedReader file;
  32. try {
  33. file = new BufferedReader(new FileReader(traceFile));
  34. readJPDA(file);
  35. file.close();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40.  
  41. private void readJPDA(BufferedReader file) throws IOException {
  42. // トレースファイル読み込み
  43. String line = null;
  44. String[] columns;
  45. String[] columns2;
  46. String[] stack;
  47. String[] signature;
  48. String threadId;
  49. String threadName;
  50. HashMap<String, Integer> threadCallDepths = new HashMap<>();
  51. int depth = 0;
  52. long timeStamp = 0L;
  53. ThreadInstanceJPDA thread = null;
  54. while ((line = file.readLine()) != null) {
  55. // トレースファイルの解析
  56. columns = line.split(":");
  57. if (columns.length < 4) continue;
  58. threadName = columns[0];
  59. threadId = columns[1];
  60. stack = columns[2].split(" ");
  61. columns2 = columns[3].split("\t");
  62. if (columns2.length < 2) continue;
  63. timeStamp = Integer.parseInt(stack[stack.length - 1]) * 60
  64. + Integer.parseInt(columns2[0]);
  65. depth = stack.length - 1;
  66. signature = columns2[1].split(" -- ");
  67. thread = threads.get(threadName);
  68. if (thread == null) {
  69. thread = new ThreadInstanceJPDA(threadName);
  70. threads.put(threadName, thread);
  71. threadCallDepths.put(threadName, 0);
  72. }
  73. if (signature.length < 2) continue;
  74. for (int i = 0; i < threadCallDepths.get(threadName) - depth + 1; i++) {
  75. thread.returnMethod();
  76. }
  77. thread.callMethod(signature[1] + "." + signature[0] + "()", timeStamp);
  78. threadCallDepths.put(threadName, depth);
  79. }
  80. }
  81. /**
  82. * メソッド毎に全メソッド実行を全てのスレッドから取り出す
  83. * @return メソッドシグニチャからメソッド実行のリストへのHashMap
  84. */
  85. public HashMap<String, ArrayList<MethodExecutionJPDA>> getAllMethodExecutions() {
  86. final HashMap<String, ArrayList<MethodExecutionJPDA>> results = new HashMap<>();
  87. for (ThreadInstanceJPDA thread: threads.values()) {
  88. thread.traverseMethodExecutionsBackward(new MethodExecutionJPDA.IMethodExecutionVisitorJPDA() {
  89. @Override
  90. public boolean preVisitThread(ThreadInstanceJPDA thread) {
  91. return false;
  92. }
  93. @Override
  94. public boolean postVisitThread(ThreadInstanceJPDA thread) {
  95. return false;
  96. }
  97. @Override
  98. public boolean preVisitMethodExecution(MethodExecutionJPDA methodExecution) {
  99. ArrayList<MethodExecutionJPDA> executions = results.get(methodExecution.getSignature());
  100. if (executions == null) {
  101. executions = new ArrayList<MethodExecutionJPDA>();
  102. results.put(methodExecution.getSignature(), executions);
  103. }
  104. executions.add(methodExecution);
  105. return false;
  106. }
  107. @Override
  108. public boolean postVisitMethodExecution(MethodExecutionJPDA methodExecution, ArrayList<MethodExecutionJPDA> children) {
  109. return false;
  110. }
  111. });
  112. }
  113. return results;
  114. }
  115.  
  116. /**
  117. * 全メソッドのシグニチャを取得する
  118. * @return 全メソッドシグニチャ
  119. */
  120. public HashSet<String> getAllMethodSignatures() {
  121. final HashSet<String> results = new HashSet<String>();
  122. for (ThreadInstanceJPDA thread: threads.values()) {
  123. thread.traverseMethodExecutionsBackward(new MethodExecutionJPDA.IMethodExecutionVisitorJPDA() {
  124. @Override
  125. public boolean preVisitThread(ThreadInstanceJPDA thread) {
  126. return false;
  127. }
  128. @Override
  129. public boolean postVisitThread(ThreadInstanceJPDA thread) {
  130. return false;
  131. }
  132. @Override
  133. public boolean preVisitMethodExecution(MethodExecutionJPDA methodExecution) {
  134. results.add(methodExecution.getSignature());
  135. return false;
  136. }
  137. @Override
  138. public boolean postVisitMethodExecution(MethodExecutionJPDA methodExecution, ArrayList<MethodExecutionJPDA> children) {
  139. return false;
  140. }
  141. });
  142. }
  143. return results;
  144. }
  145. public void traverseMethodExecutionsBackward(MethodExecutionJPDA.IMethodExecutionVisitorJPDA visitor) {
  146. for (ThreadInstanceJPDA thread: threads.values()) {
  147. visitor.preVisitThread(thread);
  148. thread.traverseMethodExecutionsBackward(visitor);
  149. visitor.postVisitThread(thread);
  150. }
  151. }
  152. }