private ThreadObjectGCRoot getOOMEThread(Heap heap) {
    Collection<GCRoot> roots = heap.getGCRoots();

    for (GCRoot root : roots) {
      if (root.getKind().equals(GCRoot.THREAD_OBJECT)) {
        ThreadObjectGCRoot threadRoot = (ThreadObjectGCRoot) root;
        StackTraceElement[] stackTrace = threadRoot.getStackTrace();

        if (stackTrace != null && stackTrace.length >= 1) {
          StackTraceElement ste = stackTrace[0];

          if (OutOfMemoryError.class.getName().equals(ste.getClassName())
              && "<init>".equals(ste.getMethodName())) {
            return threadRoot;
          }
        }
      }
    }
    return null;
  }
  private synchronized String getStackTrace() {
    if (stackTrace == null) {
      boolean gotoSourceAvailable =
          heapFragmentWalker.getHeapDumpProject() != null && GoToSource.isAvailable();
      StringBuilder sb = new StringBuilder();
      Heap h = heapFragmentWalker.getHeapFragment();
      Collection<GCRoot> roots = h.getGCRoots();
      Map<ThreadObjectGCRoot, Map<Integer, List<JavaFrameGCRoot>>> javaFrameMap =
          computeJavaFrameMap(roots);
      // Use this to enable VisualVM color scheme for threads dumps:
      // sw.append("<pre style='color: #cc3300;'>"); // NOI18N
      sb.append("<pre>"); // NOI18N
      for (GCRoot root : roots) {
        if (root.getKind().equals(GCRoot.THREAD_OBJECT)) {
          ThreadObjectGCRoot threadRoot = (ThreadObjectGCRoot) root;
          Instance threadInstance = threadRoot.getInstance();
          if (threadInstance != null) {
            String threadName = getThreadName(threadInstance);
            Boolean daemon = (Boolean) threadInstance.getValueOfField("daemon"); // NOI18N
            Integer priority = (Integer) threadInstance.getValueOfField("priority"); // NOI18N
            Long threadId = (Long) threadInstance.getValueOfField("tid"); // NOI18N
            Integer threadStatus =
                (Integer) threadInstance.getValueOfField("threadStatus"); // NOI18N
            StackTraceElement stack[] = threadRoot.getStackTrace();
            Map<Integer, List<JavaFrameGCRoot>> localsMap = javaFrameMap.get(threadRoot);
            String style = "";

            if (threadRoot.equals(oome)) {
              style = "style=\"color: #FF0000\"";
            }
            // --- Use this to enable VisualVM color scheme for threads dumps: ---
            // sw.append("&nbsp;&nbsp;<span style=\"color: #0033CC\">"); // NOI18N
            sb.append("&nbsp;&nbsp;<a name=")
                .append(threadInstance.getInstanceId())
                .append("></a><b ")
                .append(style)
                .append(">"); // NOI18N
            // -------------------------------------------------------------------
            sb.append("\"")
                .append(htmlize(threadName))
                .append("\"")
                .append(daemon.booleanValue() ? " daemon" : "")
                .append(" prio=")
                .append(priority); // NOI18N
            if (threadId != null) {
              sb.append(" tid=").append(threadId); // NOI18N
            }
            if (threadStatus != null) {
              State tState = sun.misc.VM.toThreadState(threadStatus.intValue());
              sb.append(" ").append(tState); // NOI18N
            }
            // --- Use this to enable VisualVM color scheme for threads dumps: ---
            // sw.append("</span><br>"); // NOI18N
            sb.append("</b><br>"); // NOI18N
            // -------------------------------------------------------------------
            if (stack != null) {
              for (int i = 0; i < stack.length; i++) {
                String stackElHref;
                StackTraceElement stackElement = stack[i];
                String stackElementText = htmlize(stackElement.toString());

                if (gotoSourceAvailable) {
                  String className = stackElement.getClassName();
                  String method = stackElement.getMethodName();
                  int lineNo = stackElement.getLineNumber();
                  String stackUrl =
                      OPEN_THREADS_URL + className + "|" + method + "|" + lineNo; // NOI18N

                  // --- Use this to enable VisualVM color scheme for threads dumps: ---
                  // stackElHref = "&nbsp;&nbsp;<a style=\"color: #CC3300;\"
                  // href=\""+stackUrl+"\">"+stackElement+"</a>"; // NOI18N
                  stackElHref =
                      "<a href=\"" + stackUrl + "\">" + stackElementText + "</a>"; // NOI18N
                  // -------------------------------------------------------------------
                } else {
                  stackElHref = stackElementText;
                }
                sb.append("\tat ").append(stackElHref).append("<br>"); // NOI18N
                if (localsMap != null) {
                  List<JavaFrameGCRoot> locals = localsMap.get(Integer.valueOf(i));

                  if (locals != null) {
                    for (JavaFrameGCRoot localVar : locals) {
                      Instance localInstance = localVar.getInstance();

                      if (localInstance != null) {
                        sb.append("\t   Local Variable: ")
                            .append(printInstance(localInstance))
                            .append("<br>"); // NOI18N
                      } else {
                        sb.append(
                            "\t   Unknown Local Variable<br>"); // NOI18N
                      }
                    }
                  }
                }
              }
            }
          } else {
            sb.append("&nbsp;&nbsp;Unknown thread"); // NOI18N
          }
          sb.append("<br>"); // NOI18N
        }
      }
      sb.append("</pre>"); // NOI18N
      stackTrace = sb.toString();
    }
    return stackTrace;
  }
  public String computeSummary() {
    File file = heapFragmentWalker.getHeapDumpFile();
    Heap heap = heapFragmentWalker.getHeapFragment();
    HeapSummary hsummary = heap.getSummary();
    long finalizers = computeFinalizers(heap);
    int nclassloaders = 0;
    JavaClass cl = heap.getJavaClassByName("java.lang.ClassLoader"); // NOI18N
    NumberFormat numberFormat = (NumberFormat) NumberFormat.getInstance().clone();
    numberFormat.setMaximumFractionDigits(1);

    oome = getOOMEThread(heap);
    if (cl != null) {
      nclassloaders = cl.getInstancesCount();

      Collection<JavaClass> jcs = cl.getSubClasses();

      for (JavaClass jc : jcs) {
        nclassloaders += jc.getInstancesCount();
      }
    }

    String filename =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_FileItemString(
                file != null && file.exists()
                    ? file.getAbsolutePath()
                    : Bundle.OverviewController_NotAvailableMsg());

    String filesize =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_FileSizeItemString(
                file != null && file.exists()
                    ? numberFormat.format(file.length() / (1024 * 1024.0)) + " MB"
                    : // NOI18N
                    Bundle.OverviewController_NotAvailableMsg());

    String dateTaken =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_DateTakenItemString(
                new Date(hsummary.getTime()).toString());

    String liveBytes =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_TotalBytesItemString(
                numberFormat.format(hsummary.getTotalLiveBytes()));

    String liveClasses =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_TotalClassesItemString(
                numberFormat.format(heap.getAllClasses().size()));

    String liveInstances =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_TotalInstancesItemString(
                numberFormat.format(hsummary.getTotalLiveInstances()));

    String classloaders =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_ClassloadersItemString(numberFormat.format(nclassloaders));

    String gcroots =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_GcRootsItemString(
                numberFormat.format(heap.getGCRoots().size()));

    String finalizersInfo =
        "&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
            + Bundle.OverviewController_FinalizersItemString(numberFormat.format(finalizers));

    String oomeString = "";
    if (oome != null) {
      Instance thread = oome.getInstance();
      String threadName = htmlize(getThreadName(thread));
      String threadUrl =
          "<a href='"
              + THREAD_URL_PREFIX
              + thread.getJavaClass().getName()
              + "/"
              + thread.getInstanceId()
              + "'>"
              + threadName
              + "</a>"; // NOI18N
      oomeString =
          "<br><br>&nbsp;&nbsp;&nbsp;&nbsp;" // NOI18N
              + Bundle.OverviewController_OOMELabelString()
              + "<br>&nbsp;&nbsp;&nbsp;&nbsp;"
              + Bundle.OverviewController_OOMEItemString(threadUrl);
    }
    String memoryRes = Icons.getResource(ProfilerIcons.HEAP_DUMP);
    return "<b><img border='0' align='bottom' src='nbresloc:/"
        + memoryRes
        + "'>&nbsp;&nbsp;" // NOI18N
        + Bundle.OverviewController_SummaryString()
        + "</b><br><hr>"
        + dateTaken
        + "<br>"
        + filename
        + "<br>"
        + filesize
        + "<br><br>"
        + liveBytes // NOI18N
        + "<br>"
        + liveClasses
        + "<br>"
        + liveInstances
        + "<br>"
        + classloaders
        + "<br>"
        + gcroots
        + "<br>"
        + finalizersInfo
        + oomeString; // NOI18N
  }