You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TracingEventQueueThread.java 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) 2007, Kirill Grouchnikov
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * - Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. * - Neither the name of the <ORGANIZATION> nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  21. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. package com.dmdirc.addons.ui_swing;
  30. import java.awt.AWTEvent;
  31. import java.lang.management.ManagementFactory;
  32. import java.lang.management.ThreadInfo;
  33. import java.lang.management.ThreadMXBean;
  34. import java.util.HashMap;
  35. import java.util.Map;
  36. import java.util.Set;
  37. import javax.management.MBeanServer;
  38. import javax.management.ObjectName;
  39. /**
  40. * Event queue extention to monitor long running tasks on the EDT. Found at
  41. * http://today.java.net/lpt/a/433
  42. */
  43. class TracingEventQueueThread extends Thread {
  44. private long thresholdDelay;
  45. private Map<AWTEvent, Long> eventTimeMap;
  46. private ThreadMXBean threadBean;
  47. private boolean running = false;
  48. /**
  49. * Instantiates a new tracing thread.
  50. *
  51. * @param thresholdDelay Length to consider a long running task
  52. */
  53. public TracingEventQueueThread(long thresholdDelay) {
  54. this.thresholdDelay = thresholdDelay;
  55. this.eventTimeMap = new HashMap<AWTEvent, Long>();
  56. try {
  57. MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
  58. ObjectName objName = new ObjectName(
  59. ManagementFactory.THREAD_MXBEAN_NAME);
  60. Set<ObjectName> mbeans = mbeanServer.queryNames(objName, null);
  61. for (ObjectName name : mbeans) {
  62. this.threadBean = ManagementFactory.newPlatformMXBeanProxy(
  63. mbeanServer, name.toString(), ThreadMXBean.class);
  64. }
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. /**
  70. * Marks the start time for the specified event.
  71. *
  72. * @param event Event to monitor
  73. */
  74. public synchronized void eventDispatched(AWTEvent event) {
  75. this.eventTimeMap.put(event, System.currentTimeMillis());
  76. }
  77. /**
  78. * Marks the end time for the specified event.
  79. *
  80. * @param event Event to finish monitoring.
  81. */
  82. public synchronized void eventProcessed(AWTEvent event) {
  83. this.checkEventTime(event, System.currentTimeMillis(),
  84. this.eventTimeMap.get(event));
  85. this.eventTimeMap.put(event, null);
  86. }
  87. private void checkEventTime(AWTEvent event, long currTime, long startTime) {
  88. long currProcessingTime = currTime - startTime;
  89. if (currProcessingTime >= this.thresholdDelay) {
  90. System.out.println("Event [" + event.hashCode() + "] " + event.
  91. getClass().getName() + " is taking too much time on EDT (" +
  92. currProcessingTime + ")");
  93. if (this.threadBean != null) {
  94. long threadIds[] = threadBean.getAllThreadIds();
  95. for (long threadId : threadIds) {
  96. ThreadInfo threadInfo = threadBean.getThreadInfo(threadId,
  97. Integer.MAX_VALUE);
  98. if (threadInfo != null && threadInfo.getThreadName().
  99. startsWith("AWT-EventQueue")) {
  100. System.out.println(threadInfo.getThreadName() + " / " +
  101. threadInfo.getThreadState());
  102. StackTraceElement[] stack = threadInfo.getStackTrace();
  103. for (StackTraceElement stackEntry : stack) {
  104. System.out.println("\t" + stackEntry.getClassName() +
  105. "." + stackEntry.getMethodName() + " [" +
  106. stackEntry.getLineNumber() + "]");
  107. }
  108. }
  109. }
  110. long[] deadlockedThreads = threadBean.findDeadlockedThreads();
  111. if ((deadlockedThreads != null) &&
  112. (deadlockedThreads.length > 0)) {
  113. System.out.println("Deadlocked threads:");
  114. for (long threadId : deadlockedThreads) {
  115. ThreadInfo threadInfo = threadBean.getThreadInfo(
  116. threadId, Integer.MAX_VALUE);
  117. System.out.println(threadInfo.getThreadName() + " / " +
  118. threadInfo.getThreadState());
  119. StackTraceElement[] stack = threadInfo.getStackTrace();
  120. for (StackTraceElement stackEntry : stack) {
  121. System.out.println("\t" + stackEntry.getClassName() +
  122. "." + stackEntry.getMethodName() + " [" +
  123. stackEntry.getLineNumber() + "]");
  124. }
  125. }
  126. }
  127. }
  128. }
  129. }
  130. /** {@inheritDoc} */
  131. @Override
  132. public void run() {
  133. running = true;
  134. while (running) {
  135. long currTime = System.currentTimeMillis();
  136. synchronized (this) {
  137. for (Map.Entry<AWTEvent, Long> entry : this.eventTimeMap.
  138. entrySet()) {
  139. AWTEvent event = entry.getKey();
  140. if (entry.getValue() == null) {
  141. continue;
  142. }
  143. long startTime = entry.getValue();
  144. this.checkEventTime(event, currTime, startTime);
  145. }
  146. }
  147. try {
  148. Thread.sleep(100);
  149. } catch (InterruptedException ie) {
  150. }
  151. }
  152. }
  153. /**
  154. * Cancels this thread.
  155. */
  156. public void cancel() {
  157. running = false;
  158. }
  159. }