Source Code Cross Referenced for EDTDebugQueue.java in  » Swing-Library » swingexplorer » org » swingexplorer » edt_monitor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » swingexplorer » org.swingexplorer.edt_monitor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Swing Explorer. Tool for developers exploring Java/Swing-based application internals. 
003:         * Copyright (C) 2008, Maxim Zakharenkov
004:         *
005:         * This program is free software; you can redistribute it and/or modify
006:         * it under the terms of the GNU General Public License as published by
007:         * the Free Software Foundation; either version 2 of the License, or
008:         * (at your option) any later version.
009:         *
010:         * This program is distributed in the hope that it will be useful,
011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013:         * GNU General Public License for more details.
014:         *
015:         * You should have received a copy of the GNU General Public License along
016:         * with this program; if not, write to the Free Software Foundation, Inc.,
017:         * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
018:         * 
019:         * $Header: /cvs/swingexplorer/src/org/swingexplorer/edt_monitor/EDTDebugQueue.java,v 1.1 2008/03/07 11:46:52 maxz1 Exp $
020:         */
021:        package org.swingexplorer.edt_monitor;
022:
023:        import java.awt.AWTEvent;
024:        import java.awt.EventQueue;
025:        import java.awt.Toolkit;
026:        import java.awt.event.WindowEvent;
027:        import java.text.MessageFormat;
028:        import java.util.LinkedList;
029:        import java.util.Timer;
030:        import java.util.TimerTask;
031:
032:        import org.swingexplorer.Problem;
033:        import org.swingexplorer.ProblemListener;
034:
035:        /**
036:         *
037:         * @author Elliott Hughes <enh@jessies.org>
038:         * 
039:         * Advice, bug fixes, and test cases from
040:         * Alexander Potochkin and Oleg Sukhodolsky.
041:         * 
042:         * https://swinghelper.dev.java.net/
043:         * 
044:         * Adoption for Swing Explorer by Maxim Zakharenkov 
045:         * https://swingexplorer.dev.java.net/
046:         */
047:        public class EDTDebugQueue extends EventQueue {
048:
049:            // Time to wait between checks that the event dispatch thread isn't hung.
050:            private static final long CHECK_INTERVAL_MS = 100;
051:
052:            // Help distinguish multiple hangs in the log, and match start and end too.
053:            // Only access this via getNewHangNumber.
054:            private static int hangCount = 0;
055:
056:            // Prevents us complaining about hangs during start-up, which are probably
057:            // the JVM vendor's fault.
058:            private boolean haveShownSomeComponent = false;
059:
060:            // The currently outstanding event dispatches. The implementation of
061:            // modal dialogs is a common cause for multiple outstanding dispatches.
062:            private final LinkedList<DispatchInfo> dispatches = new LinkedList<DispatchInfo>();
063:
064:            static long minimalMonitoredHangTime = 1000;
065:            static EDTDebugQueue instance = new EDTDebugQueue();
066:            static ProblemListener problemListener;
067:
068:            public static void setProblemListener(
069:                    ProblemListener _problemListener) {
070:                problemListener = _problemListener;
071:            }
072:
073:            private static void notifyProblemListener(long delay, AWTEvent event) {
074:                if (problemListener == null) {
075:                    return;
076:                }
077:
078:                // obtain stack information
079:                StackTraceElement[] trace = Thread.currentThread()
080:                        .getStackTrace();
081:                final StackTraceElement[] newTrace = new StackTraceElement[trace.length - 3];
082:                System.arraycopy(trace, 3, newTrace, 0, newTrace.length);
083:
084:                // notify
085:                String description = MessageFormat.format(
086:                        "Warning: EDT delay for {0}ms in the event {1}", delay,
087:                        event.paramString());
088:                problemListener.problemOccured(new Problem(description,
089:                        newTrace));
090:            }
091:
092:            public static EDTDebugQueue getInstance() {
093:                return instance;
094:            }
095:
096:            public static void initMonitoring() {
097:                Toolkit.getDefaultToolkit().getSystemEventQueue()
098:                        .push(instance);
099:            }
100:
101:            public static long getMinimalMonitoredHangTime() {
102:                return minimalMonitoredHangTime;
103:            }
104:
105:            public static void setMinimalMonitoredHangTime(
106:                    long _minimalMonitoredHangTime) {
107:                minimalMonitoredHangTime = _minimalMonitoredHangTime;
108:            }
109:
110:            private static class DispatchInfo {
111:                // The last-dumped hung stack trace for this dispatch.
112:                private StackTraceElement[] lastReportedStack;
113:                // If so; what was the identifying hang number?
114:                private int hangNumber;
115:
116:                // The EDT for this dispatch (for the purpose of getting stack traces).
117:                // I don't know of any API for getting the event dispatch thread,
118:                // but we can assume that it's the current thread if we're in the
119:                // middle of dispatching an AWT event...
120:                // We can't cache this because the EDT can die and be replaced by a
121:                // new EDT if there's an uncaught exception.
122:                private final Thread eventDispatchThread = Thread
123:                        .currentThread();
124:
125:                // The last time in milliseconds at which we saw a dispatch on the above thread.
126:                private long lastDispatchTimeMillis = System
127:                        .currentTimeMillis();
128:
129:                public DispatchInfo() {
130:                    // All initialization is done by the field initializers.
131:                }
132:
133:                public void checkForHang() {
134:                    if (timeSoFar() > getMinimalMonitoredHangTime()) {
135:                        examineHang();
136:                    }
137:                }
138:
139:                // We can't use StackTraceElement.equals because that insists on checking the filename and line number.
140:                // That would be version-specific.
141:                private static boolean stackTraceElementIs(StackTraceElement e,
142:                        String className, String methodName, boolean isNative) {
143:                    return e.getClassName().equals(className)
144:                            && e.getMethodName().equals(methodName)
145:                            && e.isNativeMethod() == isNative;
146:                }
147:
148:                // Checks whether the given stack looks like it's waiting for another event.
149:                // This relies on JDK implementation details.
150:                private boolean isWaitingForNextEvent(
151:                        StackTraceElement[] currentStack) {
152:                    return stackTraceElementIs(currentStack[0],
153:                            "java.lang.Object", "wait", true)
154:                            && stackTraceElementIs(currentStack[1],
155:                                    "java.lang.Object", "wait", false)
156:                            && stackTraceElementIs(currentStack[2],
157:                                    "java.awt.EventQueue", "getNextEvent",
158:                                    false);
159:                }
160:
161:                private void examineHang() {
162:                    StackTraceElement[] currentStack = eventDispatchThread
163:                            .getStackTrace();
164:
165:                    if (isWaitingForNextEvent(currentStack)) {
166:                        // Don't be fooled by a modal dialog if it's waiting for its next event.
167:                        // As long as the modal dialog's event pump doesn't get stuck, it's okay for the outer pump to be suspended.
168:                        return;
169:                    }
170:
171:                    if (stacksEqual(lastReportedStack, currentStack)) {
172:                        // Don't keep reporting the same hang every time the timer goes off.
173:                        return;
174:                    }
175:
176:                    hangNumber = getNewHangNumber();
177:                    lastReportedStack = currentStack;
178:
179:                    String description = MessageFormat.format(
180:                            "EDT delay for {0}ms", timeSoFar());
181:                    fireProblem(new Problem(description, currentStack));
182:                }
183:
184:                private static boolean stacksEqual(StackTraceElement[] a,
185:                        StackTraceElement[] b) {
186:                    if (a == null) {
187:                        return false;
188:                    }
189:                    if (a.length != b.length) {
190:                        return false;
191:                    }
192:                    for (int i = 0; i < a.length; ++i) {
193:                        if (a[i].equals(b[i]) == false) {
194:                            return false;
195:                        }
196:                    }
197:                    return true;
198:                }
199:
200:                /**
201:                 * Returns how long this dispatch has been going on (in milliseconds).
202:                 */
203:                private long timeSoFar() {
204:                    return (System.currentTimeMillis() - lastDispatchTimeMillis);
205:                }
206:
207:                public void dispose() {
208:                    if (lastReportedStack != null) {
209:                        String description = MessageFormat.format(
210:                                "EDT delay end after {0}ms", timeSoFar());
211:                        fireProblem(new Problem(description, lastReportedStack));
212:                    }
213:                }
214:
215:                private void fireProblem(Problem problem) {
216:                    if (problemListener != null) {
217:                        problemListener.problemOccured(problem);
218:                    }
219:                }
220:            }
221:
222:            private EDTDebugQueue() {
223:                initTimer();
224:            }
225:
226:            /**
227:             * Sets up a timer to check for hangs frequently.
228:             */
229:            private void initTimer() {
230:                final long initialDelayMs = 0;
231:                final boolean isDaemon = true;
232:                Timer timer = new Timer("EventDispatchThreadHangMonitor",
233:                        isDaemon);
234:                timer.schedule(new HangChecker(), initialDelayMs,
235:                        CHECK_INTERVAL_MS);
236:            }
237:
238:            private class HangChecker extends TimerTask {
239:                @Override
240:                public void run() {
241:                    synchronized (dispatches) {
242:                        if (dispatches.isEmpty() || !haveShownSomeComponent) {
243:                            // Nothing to do.
244:                            // We don't destroy the timer when there's nothing happening
245:                            // because it would mean a lot more work on every single AWT
246:                            // event that gets dispatched.
247:                            return;
248:                        }
249:                        // Only the most recent dispatch can be hung; nested dispatches
250:                        // by their nature cause the outer dispatch pump to be suspended.
251:                        dispatches.getLast().checkForHang();
252:                    }
253:                }
254:            }
255:
256:            /**
257:             * Overrides EventQueue.dispatchEvent to call our pre and post hooks either
258:             * side of the system's event dispatch code.
259:             */
260:            @Override
261:            protected void dispatchEvent(AWTEvent event) {
262:                try {
263:                    preDispatchEvent();
264:                    super .dispatchEvent(event);
265:                } finally {
266:                    postDispatchEvent();
267:                    if (!haveShownSomeComponent && event instanceof  WindowEvent
268:                            && event.getID() == WindowEvent.WINDOW_OPENED) {
269:                        haveShownSomeComponent = true;
270:                    }
271:                }
272:            }
273:
274:            private void debug(String which) {
275:                if (false) {
276:                    for (int i = dispatches.size(); i >= 0; --i) {
277:                        System.out.print(' ');
278:                    }
279:                    System.out.println(which);
280:                }
281:            }
282:
283:            /**
284:             * Starts tracking a dispatch.
285:             */
286:            private synchronized void preDispatchEvent() {
287:                debug("pre");
288:                synchronized (dispatches) {
289:                    dispatches.addLast(new DispatchInfo());
290:                }
291:            }
292:
293:            /**
294:             * Stops tracking a dispatch.
295:             */
296:            private synchronized void postDispatchEvent() {
297:                synchronized (dispatches) {
298:                    // We've finished the most nested dispatch, and don't need it any longer.
299:                    DispatchInfo justFinishedDispatch = dispatches.removeLast();
300:                    justFinishedDispatch.dispose();
301:
302:                    // The other dispatches, which have been waiting, need to be credited extra time.
303:                    // We do this rather simplistically by pretending they've just been redispatched.
304:                    Thread currentEventDispatchThread = Thread.currentThread();
305:                    for (DispatchInfo dispatchInfo : dispatches) {
306:                        if (dispatchInfo.eventDispatchThread == currentEventDispatchThread) {
307:                            dispatchInfo.lastDispatchTimeMillis = System
308:                                    .currentTimeMillis();
309:                        }
310:                    }
311:                }
312:                debug("post");
313:            }
314:
315:            private static String stackTraceToString(
316:                    StackTraceElement[] stackTrace) {
317:                StringBuilder result = new StringBuilder();
318:                // We used to avoid showing any code above where this class gets
319:                // involved in event dispatch, but that hides potentially useful
320:                // information when dealing with modal dialogs. Maybe we should
321:                // reinstate that, but search from the other end of the stack?
322:                for (StackTraceElement stackTraceElement : stackTrace) {
323:                    String indentation = "    ";
324:                    result.append("\n" + indentation + stackTraceElement);
325:                }
326:                return result.toString();
327:            }
328:
329:            private synchronized static int getNewHangNumber() {
330:                return ++hangCount;
331:            }
332:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.