History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/example/trace/EventThread.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/example/trace/EventThread.java+344−0
@@ -0,0 +1,344 @@
1/*
2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.example.trace;
27
28import com.sun.jdi.*;
29import com.sun.jdi.request.*;
30import com.sun.jdi.event.*;
31
32import java.util.*;
33import java.io.PrintWriter;
34
35/**
36 * This class processes incoming JDI events and displays them
37 *
38 * @author Robert Field
39 */
40public class EventThread extends Thread {
41
42 private final VirtualMachine vm; // Running VM
43 private final String[] excludes; // Packages to exclude
44 private final PrintWriter writer; // Where output goes
45
46 static String nextBaseIndent = ""; // Starting indent for next thread
47
48 private boolean connected = true; // Connected to VM
49 private boolean vmDied = true; // VMDeath occurred
50
51 // Maps ThreadReference to ThreadTrace instances
52 private Map<ThreadReference, ThreadTrace> traceMap =
53 new HashMap<>();
54
55 EventThread(VirtualMachine vm, String[] excludes, PrintWriter writer) {
56 super("event-handler");
57 this.vm = vm;
58 this.excludes = excludes;
59 this.writer = writer;
60 }
61
62 /**
63 * Run the event handling thread.
64 * As long as we are connected, get event sets off
65 * the queue and dispatch the events within them.
66 */
67 @Override
68 public void run() {
69 EventQueue queue = vm.eventQueue();
70 while (connected) {
71 try {
72 EventSet eventSet = queue.remove();
73 EventIterator it = eventSet.eventIterator();
74 while (it.hasNext()) {
75 handleEvent(it.nextEvent());
76 }
77 eventSet.resume();
78 } catch (InterruptedException exc) {
79 // Ignore
80 } catch (VMDisconnectedException discExc) {
81 handleDisconnectedException();
82 break;
83 }
84 }
85 }
86
87 /**
88 * Create the desired event requests, and enable
89 * them so that we will get events.
90 * @param excludes Class patterns for which we don't want events
91 * @param watchFields Do we want to watch assignments to fields
92 */
93 void setEventRequests(boolean watchFields) {
94 EventRequestManager mgr = vm.eventRequestManager();
95
96 // want all exceptions
97 ExceptionRequest excReq = mgr.createExceptionRequest(null,
98 true, true);
99 // suspend so we can step
100 excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL);
101 excReq.enable();
102
103 MethodEntryRequest menr = mgr.createMethodEntryRequest();
104 for (int i=0; i<excludes.length; ++i) {
105 menr.addClassExclusionFilter(excludes[i]);
106 }
107 menr.setSuspendPolicy(EventRequest.SUSPEND_NONE);
108 menr.enable();
109
110 MethodExitRequest mexr = mgr.createMethodExitRequest();
111 for (int i=0; i<excludes.length; ++i) {
112 mexr.addClassExclusionFilter(excludes[i]);
113 }
114 mexr.setSuspendPolicy(EventRequest.SUSPEND_NONE);
115 mexr.enable();
116
117 ThreadDeathRequest tdr = mgr.createThreadDeathRequest();
118 // Make sure we sync on thread death
119 tdr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
120 tdr.enable();
121
122 if (watchFields) {
123 ClassPrepareRequest cpr = mgr.createClassPrepareRequest();
124 for (int i=0; i<excludes.length; ++i) {
125 cpr.addClassExclusionFilter(excludes[i]);
126 }
127 cpr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
128 cpr.enable();
129 }
130 }
131
132 /**
133 * This class keeps context on events in one thread.
134 * In this implementation, context is the indentation prefix.
135 */
136 class ThreadTrace {
137 final ThreadReference thread;
138 final String baseIndent;
139 static final String threadDelta = " ";
140 StringBuffer indent;
141
142 ThreadTrace(ThreadReference thread) {
143 this.thread = thread;
144 this.baseIndent = nextBaseIndent;
145 indent = new StringBuffer(baseIndent);
146 nextBaseIndent += threadDelta;
147 println("====== " + thread.name() + " ======");
148 }
149
150 private void println(String str) {
151 writer.print(indent);
152 writer.println(str);
153 }
154
155 void methodEntryEvent(MethodEntryEvent event) {
156 println(event.method().name() + " -- "
157 + event.method().declaringType().name());
158 indent.append("| ");
159 }
160
161 void methodExitEvent(MethodExitEvent event) {
162 indent.setLength(indent.length()-2);
163 }
164
165 void fieldWatchEvent(ModificationWatchpointEvent event) {
166 Field field = event.field();
167 Value value = event.valueToBe();
168 println(" " + field.name() + " = " + value);
169 }
170
171 void exceptionEvent(ExceptionEvent event) {
172 println("Exception: " + event.exception() +
173 " catch: " + event.catchLocation());
174
175 // Step to the catch
176 EventRequestManager mgr = vm.eventRequestManager();
177 StepRequest req = mgr.createStepRequest(thread,
178 StepRequest.STEP_MIN,
179 StepRequest.STEP_INTO);
180 req.addCountFilter(1); // next step only
181 req.setSuspendPolicy(EventRequest.SUSPEND_ALL);
182 req.enable();
183 }
184
185 // Step to exception catch
186 void stepEvent(StepEvent event) {
187 // Adjust call depth
188 int cnt = 0;
189 indent = new StringBuffer(baseIndent);
190 try {
191 cnt = thread.frameCount();
192 } catch (IncompatibleThreadStateException exc) {
193 }
194 while (cnt-- > 0) {
195 indent.append("| ");
196 }
197
198 EventRequestManager mgr = vm.eventRequestManager();
199 mgr.deleteEventRequest(event.request());
200 }
201
202 void threadDeathEvent(ThreadDeathEvent event) {
203 indent = new StringBuffer(baseIndent);
204 println("====== " + thread.name() + " end ======");
205 }
206 }
207
208 /**
209 * Returns the ThreadTrace instance for the specified thread,
210 * creating one if needed.
211 */
212 ThreadTrace threadTrace(ThreadReference thread) {
213 ThreadTrace trace = traceMap.get(thread);
214 if (trace == null) {
215 trace = new ThreadTrace(thread);
216 traceMap.put(thread, trace);
217 }
218 return trace;
219 }
220
221 /**
222 * Dispatch incoming events
223 */
224 private void handleEvent(Event event) {
225 if (event instanceof ExceptionEvent) {
226 exceptionEvent((ExceptionEvent)event);
227 } else if (event instanceof ModificationWatchpointEvent) {
228 fieldWatchEvent((ModificationWatchpointEvent)event);
229 } else if (event instanceof MethodEntryEvent) {
230 methodEntryEvent((MethodEntryEvent)event);
231 } else if (event instanceof MethodExitEvent) {
232 methodExitEvent((MethodExitEvent)event);
233 } else if (event instanceof StepEvent) {
234 stepEvent((StepEvent)event);
235 } else if (event instanceof ThreadDeathEvent) {
236 threadDeathEvent((ThreadDeathEvent)event);
237 } else if (event instanceof ClassPrepareEvent) {
238 classPrepareEvent((ClassPrepareEvent)event);
239 } else if (event instanceof VMStartEvent) {
240 vmStartEvent((VMStartEvent)event);
241 } else if (event instanceof VMDeathEvent) {
242 vmDeathEvent((VMDeathEvent)event);
243 } else if (event instanceof VMDisconnectEvent) {
244 vmDisconnectEvent((VMDisconnectEvent)event);
245 } else {
246 throw new Error("Unexpected event type");
247 }
248 }
249
250 /***
251 * A VMDisconnectedException has happened while dealing with
252 * another event. We need to flush the event queue, dealing only
253 * with exit events (VMDeath, VMDisconnect) so that we terminate
254 * correctly.
255 */
256 synchronized void handleDisconnectedException() {
257 EventQueue queue = vm.eventQueue();
258 while (connected) {
259 try {
260 EventSet eventSet = queue.remove();
261 EventIterator iter = eventSet.eventIterator();
262 while (iter.hasNext()) {
263 Event event = iter.nextEvent();
264 if (event instanceof VMDeathEvent) {
265 vmDeathEvent((VMDeathEvent)event);
266 } else if (event instanceof VMDisconnectEvent) {
267 vmDisconnectEvent((VMDisconnectEvent)event);
268 }
269 }
270 eventSet.resume(); // Resume the VM
271 } catch (InterruptedException exc) {
272 // ignore
273 }
274 }
275 }
276
277 private void vmStartEvent(VMStartEvent event) {
278 writer.println("-- VM Started --");
279 }
280
281 // Forward event for thread specific processing
282 private void methodEntryEvent(MethodEntryEvent event) {
283 threadTrace(event.thread()).methodEntryEvent(event);
284 }
285
286 // Forward event for thread specific processing
287 private void methodExitEvent(MethodExitEvent event) {
288 threadTrace(event.thread()).methodExitEvent(event);
289 }
290
291 // Forward event for thread specific processing
292 private void stepEvent(StepEvent event) {
293 threadTrace(event.thread()).stepEvent(event);
294 }
295
296 // Forward event for thread specific processing
297 private void fieldWatchEvent(ModificationWatchpointEvent event) {
298 threadTrace(event.thread()).fieldWatchEvent(event);
299 }
300
301 void threadDeathEvent(ThreadDeathEvent event) {
302 ThreadTrace trace = traceMap.get(event.thread());
303 if (trace != null) { // only want threads we care about
304 trace.threadDeathEvent(event); // Forward event
305 }
306 }
307
308 /**
309 * A new class has been loaded.
310 * Set watchpoints on each of its fields
311 */
312 private void classPrepareEvent(ClassPrepareEvent event) {
313 EventRequestManager mgr = vm.eventRequestManager();
314 List<Field> fields = event.referenceType().visibleFields();
315 for (Field field : fields) {
316 ModificationWatchpointRequest req =
317 mgr.createModificationWatchpointRequest(field);
318 for (int i=0; i<excludes.length; ++i) {
319 req.addClassExclusionFilter(excludes[i]);
320 }
321 req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
322 req.enable();
323 }
324 }
325
326 private void exceptionEvent(ExceptionEvent event) {
327 ThreadTrace trace = traceMap.get(event.thread());
328 if (trace != null) { // only want threads we care about
329 trace.exceptionEvent(event); // Forward event
330 }
331 }
332
333 public void vmDeathEvent(VMDeathEvent event) {
334 vmDied = true;
335 writer.println("-- The application exited --");
336 }
337
338 public void vmDisconnectEvent(VMDisconnectEvent event) {
339 connected = false;
340 if (!vmDied) {
341 writer.println("-- The application has been disconnected --");
342 }
343 }
344}