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.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. /**
  48. * Instantiates a new tracing thread.
  49. *
  50. * @param thresholdDelay Length to consider a long running task
  51. */
  52. public TracingEventQueueThread(long thresholdDelay) {
  53. this.thresholdDelay = thresholdDelay;
  54. this.eventTimeMap = new HashMap<AWTEvent, Long>();
  55. try {
  56. MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
  57. ObjectName objName = new ObjectName(
  58. ManagementFactory.THREAD_MXBEAN_NAME);
  59. Set<ObjectName> mbeans = mbeanServer.queryNames(objName, null);
  60. for (ObjectName name : mbeans) {
  61. this.threadBean = ManagementFactory.newPlatformMXBeanProxy(
  62. mbeanServer, name.toString(), ThreadMXBean.class);
  63. }
  64. } catch (Exception e) {
  65. e.printStackTrace();
  66. }
  67. }
  68. /**
  69. * Marks the start time for the specified event.
  70. *
  71. * @param event Event to monitor
  72. */
  73. public synchronized void eventDispatched(AWTEvent event) {
  74. this.eventTimeMap.put(event, System.currentTimeMillis());
  75. }
  76. /**
  77. * Marks the end time for the specified event.
  78. *
  79. * @param event Event to finish monitoring.
  80. */
  81. public synchronized void eventProcessed(AWTEvent event) {
  82. this.checkEventTime(event, System.currentTimeMillis(),
  83. this.eventTimeMap.get(event));
  84. this.eventTimeMap.put(event, null);
  85. }
  86. private void checkEventTime(AWTEvent event, long currTime, long startTime) {
  87. long currProcessingTime = currTime - startTime;
  88. if (currProcessingTime >= this.thresholdDelay) {
  89. System.out.println("Event [" + event.hashCode() + "] " + event.
  90. getClass().getName() + " is taking too much time on EDT (" +
  91. currProcessingTime + ")");
  92. if (this.threadBean != null) {
  93. long threadIds[] = threadBean.getAllThreadIds();
  94. for (long threadId : threadIds) {
  95. ThreadInfo threadInfo = threadBean.getThreadInfo(threadId,
  96. Integer.MAX_VALUE);
  97. if (threadInfo != null && threadInfo.getThreadName().
  98. startsWith("AWT-EventQueue")) {
  99. System.out.println(threadInfo.getThreadName() + " / " +
  100. threadInfo.getThreadState());
  101. StackTraceElement[] stack = threadInfo.getStackTrace();
  102. for (StackTraceElement stackEntry : stack) {
  103. System.out.println("\t" + stackEntry.getClassName() +
  104. "." + stackEntry.getMethodName() + " [" +
  105. stackEntry.getLineNumber() + "]");
  106. }
  107. }
  108. }
  109. long[] deadlockedThreads = threadBean.findDeadlockedThreads();
  110. if ((deadlockedThreads != null) &&
  111. (deadlockedThreads.length > 0)) {
  112. System.out.println("Deadlocked threads:");
  113. for (long threadId : deadlockedThreads) {
  114. ThreadInfo threadInfo = threadBean.getThreadInfo(
  115. threadId, Integer.MAX_VALUE);
  116. System.out.println(threadInfo.getThreadName() + " / " +
  117. threadInfo.getThreadState());
  118. StackTraceElement[] stack = threadInfo.getStackTrace();
  119. for (StackTraceElement stackEntry : stack) {
  120. System.out.println("\t" + stackEntry.getClassName() +
  121. "." + stackEntry.getMethodName() + " [" +
  122. stackEntry.getLineNumber() + "]");
  123. }
  124. }
  125. }
  126. }
  127. }
  128. }
  129. /** {@inheritDoc} */
  130. @Override
  131. public void run() {
  132. while (true) {
  133. long currTime = System.currentTimeMillis();
  134. synchronized (this) {
  135. for (Map.Entry<AWTEvent, Long> entry : this.eventTimeMap.
  136. entrySet()) {
  137. AWTEvent event = entry.getKey();
  138. if (entry.getValue() == null) {
  139. continue;
  140. }
  141. long startTime = entry.getValue();
  142. this.checkEventTime(event, currTime, startTime);
  143. }
  144. }
  145. try {
  146. Thread.sleep(100);
  147. } catch (InterruptedException ie) {
  148. }
  149. }
  150. }
  151. }