1 /* VMVirtualMachine.java -- A reference implementation of a JDWP virtual
2    machine
3 
4    Copyright (C) 2005, 2006, 2007 Free Software Foundation
5 
6 This file is part of GNU Classpath.
7 
8 GNU Classpath is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12 
13 GNU Classpath is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GNU Classpath; see the file COPYING.  If not, write to the
20 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301 USA.
22 
23 Linking this library statically or dynamically with other modules is
24 making a combined work based on this library.  Thus, the terms and
25 conditions of the GNU General Public License cover the whole
26 combination.
27 
28 As a special exception, the copyright holders of this library give you
29 permission to link this library with independent modules to produce an
30 executable, regardless of the license terms of these independent
31 modules, and to copy and distribute the resulting executable under
32 terms of your choice, provided that you also meet, for each linked
33 terms of your choice, provided that you also meet, for each linked
34 independent module, the terms and conditions of the license of that
35 module.  An independent module is a module which is not derived from
36 or based on this library.  If you modify this library, you may extend
37 this exception to your version of the library, but you are not
38 obligated to do so.  If you do not wish to do so, delete this
39 exception statement from your version. */
40 
41 
42 package gnu.classpath.jdwp;
43 
44 import gnu.classpath.jdwp.event.EventRequest;
45 import gnu.classpath.jdwp.exception.InvalidMethodException;
46 import gnu.classpath.jdwp.exception.JdwpException;
47 import gnu.classpath.jdwp.util.MethodResult;
48 import gnu.classpath.jdwp.util.MonitorInfo;
49 import gnu.classpath.jdwp.value.Value;
50 
51 import java.util.ArrayList;
52 import java.util.Collection;
53 
54 /**
55  * A virtual machine according to JDWP.
56  *
57  * @author Keith Seitz  <keiths@redhat.com>
58  */
59 public class VMVirtualMachine
60 {
61   // VM Capabilities
62   public static final boolean canWatchFieldModification = false;
63   public static final boolean canWatchFieldAccess = false;
64   public static final boolean canGetBytecodes = false;
65   public static final boolean canGetSyntheticAttribute = false;
66   public static final boolean canGetOwnedMonitorInfo = false;
67   public static final boolean canGetCurrentContendedMonitor = false;
68   public static final boolean canGetMonitorInfo = false;
69   public static final boolean canRedefineClasses = false;
70   public static final boolean canAddMethod = false;
71   public static final boolean canUnrestrictedlyRedefineClasses = false;
72   public static final boolean canPopFrames = false;
73   public static final boolean canUseInstanceFilters = false;
74   public static final boolean canGetSourceDebugExtension = false;
75   public static final boolean canRequestVMDeathEvent = false;
76   public static final boolean canSetDefaultStratum = false;
77 
78   /**
79    * Suspend a thread
80    *
81    * @param  thread  the thread to suspend
82    */
suspendThread(Thread thread)83   public static native void suspendThread(Thread thread)
84     throws JdwpException;
85 
86   /**
87    * Suspend all threads
88    */
suspendAllThreads()89   public static void suspendAllThreads()
90     throws JdwpException
91   {
92     // Our JDWP thread group -- don't suspend any of those threads
93     Thread current = Thread.currentThread ();
94     ThreadGroup jdwpGroup = Jdwp.getDefault().getJdwpThreadGroup();
95 
96     // Find the root ThreadGroup
97     ThreadGroup group = jdwpGroup;
98     ThreadGroup parent = group.getParent ();
99     while (parent != null)
100       {
101         group = parent;
102         parent = group.getParent ();
103       }
104 
105     // Get all the threads in the system
106     int num = group.activeCount ();
107     Thread[] threads = new Thread[num];
108     group.enumerate (threads);
109 
110     for (int i = 0; i < num; ++i)
111       {
112         Thread t = threads[i];
113         if (t != null)
114           {
115             if (t.getThreadGroup () == jdwpGroup || t == current)
116               {
117                 // Don't suspend the current thread or any JDWP thread
118                 continue;
119               }
120             else
121               suspendThread (t);
122           }
123       }
124 
125     // Now suspend the current thread
126     if (current.getThreadGroup() != jdwpGroup)
127       suspendThread (current);
128   }
129 
130   /**
131    * Resume a thread. A thread must be resumed as many times
132    * as it has been suspended.
133    *
134    * @param  thread  the thread to resume
135    */
resumeThread(Thread thread)136   public static native void resumeThread(Thread thread)
137     throws JdwpException;
138 
139   /**
140    * Resume all threads. This simply decrements the thread's
141    * suspend count. It can not be used to force the application
142    * to run.
143    */
resumeAllThreads()144   public static void resumeAllThreads()
145     throws JdwpException
146   {
147     // Our JDWP thread group -- don't resume
148     Thread current = Thread.currentThread ();
149     ThreadGroup jdwpGroup = current.getThreadGroup ();
150 
151     // Find the root ThreadGroup
152     ThreadGroup group = jdwpGroup;
153     ThreadGroup parent = group.getParent ();
154     while (parent != null)
155       {
156         group = parent;
157         parent = group.getParent ();
158       }
159 
160     // Get all the threads in the system
161     int num = group.activeCount ();
162     Thread[] threads = new Thread[num];
163     group.enumerate (threads);
164 
165     for (int i = 0; i < num; ++i)
166       {
167         Thread t = threads[i];
168         if (t != null)
169           {
170             if (t.getThreadGroup () == jdwpGroup || t == current)
171               {
172                 // Don't resume the current thread or any JDWP thread
173                 continue;
174               }
175             else
176               resumeThread (t);
177           }
178       }
179   }
180 
181   /**
182    * Get the suspend count for a give thread
183    *
184    * @param  thread  the thread whose suspend count is desired
185    * @return the number of times the thread has been suspended
186    */
getSuspendCount(Thread thread)187   public static native int getSuspendCount(Thread thread)
188     throws JdwpException;
189 
190   /**
191    * Returns a Collection of all classes loaded in the VM
192    */
getAllLoadedClasses()193   public static native Collection getAllLoadedClasses()
194     throws JdwpException;
195 
196   /**
197    * Returns the status of the given class
198    *
199    * @param  clazz  the class whose status is desired
200    * @return a flag containing the class's status
201    * @see JdwpConstants.ClassStatus
202    */
getClassStatus(Class clazz)203   public static native int getClassStatus(Class clazz)
204     throws JdwpException;
205 
206   /**
207    * Returns all of the methods defined in the given class. This
208    * includes all methods, constructors, and class initializers.
209    *
210    * @param  klass  the class whose methods are desired
211    * @return an array of virtual machine methods
212    */
getAllClassMethods(Class klass)213   public static native VMMethod[] getAllClassMethods(Class klass)
214   { return null; }
215 
216   /**
217    * A factory method for getting valid virtual machine methods
218    * which may be passed to/from the debugger.
219    *
220    * @param klass the class in which the method is defined
221    * @param id    the ID of the desired method
222    * @return the desired internal representation of the method
223    * @throws InvalidMethodException if the method is not defined
224    *           in the class
225    * @throws JdwpException for any other error
226    */
getClassMethod(Class klass, long id)227   public static native VMMethod getClassMethod(Class klass, long id)
228   { return null; }
229 
230   /**
231    * Returns the thread's call stack
232    *
233    * @param  thread  thread for which to get call stack
234    * @param  start   index of first frame to return
235    * @param  length  number of frames to return (-1 for all frames)
236    * @return a list of frames
237    */
getFrames(Thread thread, int start, int length)238   public static native ArrayList getFrames(Thread thread, int start,
239                                             int length)
240     throws JdwpException;
241 
242   /**
243    * Returns the frame for a given thread with the frame ID in
244    * the buffer
245    *
246    * I don't like this.
247    *
248    * @param  thread  the frame's thread
249    * @param  bb      buffer containing the frame's ID
250    * @return the desired frame
251    */
getFrame(Thread thread, long frameID)252   public static native VMFrame getFrame(Thread thread, long frameID)
253     throws JdwpException;
254 
255   /**
256    * Returns the number of frames in the thread's stack
257    *
258    * @param  thread  the thread for which to get a frame count
259    * @return the number of frames in the thread's stack
260    */
getFrameCount(Thread thread)261   public static native int getFrameCount(Thread thread)
262     throws JdwpException;
263 
264 
265   /**
266    * Returns the status of a thread
267    *
268    * @param  thread  the thread for which to get status
269    * @return integer status of the thread
270    * @see JdwpConstants.ThreadStatus
271    */
getThreadStatus(Thread thread)272   public static native int getThreadStatus(Thread thread)
273     throws JdwpException;
274 
275   /**
276    * Returns a list of all classes which this class loader has been
277    * requested to load
278    *
279    * @param  cl  the class loader
280    * @return a list of all visible classes
281    */
getLoadRequests(ClassLoader cl)282   public static native ArrayList getLoadRequests(ClassLoader cl)
283     throws JdwpException;
284 
285   /**
286    * Executes a method in the virtual machine. The thread must already
287    * be suspended by a previous event. When the method invocation is
288    * complete, the thread (or all threads if INVOKE_SINGLE_THREADED is
289    * not set in options) must be suspended before this method returns.
290    *
291    * @param  obj         instance in which to invoke method (null for static)
292    * @param  thread      the thread in which to invoke the method
293    * @param  clazz       the class in which the method is defined
294    * @param  method      the method to invoke
295    * @param  values      arguments to pass to method
296    * @param  options     invocation options
297    * @return a result object containing the results of the invocation
298    */
executeMethod(Object obj, Thread thread, Class clazz, VMMethod method, Value[] values, int options)299   public static native MethodResult executeMethod (Object obj, Thread thread,
300                                             Class clazz, VMMethod method,
301                                             Value[] values,
302                                             int options)
303     throws JdwpException;
304 
305   /**
306    * "Returns the name of source file in which a reference type was declared"
307    *
308    * @param  clazz  the class for which to return a source file
309    * @return a string containing the source file name; "no path information
310    *         for the file is included"
311    */
getSourceFile(Class clazz)312   public static native String getSourceFile(Class clazz)
313     throws JdwpException;
314 
315   /**
316    * Register a request from the debugger
317    *
318    * Virtual machines have two options. Either do nothing and allow
319    * the event manager to take care of the request (useful for broadcast-type
320    * events like class prepare/load/unload, thread start/end, etc.)
321    * or do some internal work to set up the event notification (useful for
322    * execution-related events like breakpoints, single-stepping, etc.).
323    */
registerEvent(EventRequest request)324   public static native void registerEvent(EventRequest request)
325     throws JdwpException;
326 
327   /**
328    * Unregisters the given request
329    *
330    * @param  request  the request to unregister
331    */
unregisterEvent(EventRequest request)332   public static native void unregisterEvent(EventRequest request)
333     throws JdwpException;
334 
335 
336   /**
337    * Clear all events of the given kind
338    *
339    * @param  kind  the type of events to clear
340    */
clearEvents(byte kind)341   public static native void clearEvents(byte kind)
342     throws JdwpException;
343 
344   /**
345    * Redefines the given types. VM must support canRedefineClasses
346    * capability (may also require canAddMethod and/or
347    * canUnrestrictedlyRedefineClasses capabilities)
348    *
349    * @param types the classes to redefine
350    * @param bytecodes the new bytecode definitions for the classes
351    */
redefineClasses(Class[] types, byte[][] bytecodes)352   public static native void redefineClasses(Class[] types, byte[][] bytecodes)
353     throws JdwpException;
354 
355   /**
356    * Sets the default stratum. VM must support the
357    * canSetDefaultStratum capability.
358    *
359    * @param stratum the new default stratum or empty string to
360    *        use the reference default
361    */
setDefaultStratum(String stratum)362   public static native void setDefaultStratum(String stratum)
363     throws JdwpException;
364 
365   /**
366    * Returns the source debug extension. VM must support the
367    * canGetSourceDebugExtension capability.
368    *
369    * @param klass the class for which to return information
370    * @returns the source debug extension
371    */
getSourceDebugExtension(Class klass)372   public static native String getSourceDebugExtension(Class klass)
373     throws JdwpException;
374 
375   /**
376    * Returns the bytecode for the given method. VM must support the
377    * canGetBytecodes capability.
378    *
379    * @param method the method for which to get bytecodes
380    * @returns the bytecodes
381    */
getBytecodes(VMMethod method)382   public static native byte[] getBytecodes(VMMethod method)
383     throws JdwpException;
384 
385   /**
386    * Returns monitor information about an object. VM must support
387    * the canGetMonitorInformation capability.
388    *
389    * @param obj the object
390    * @returns monitor information (owner, entry count, waiters)
391    */
getMonitorInfo(Object obj)392   public static native MonitorInfo getMonitorInfo(Object obj)
393     throws JdwpException;
394 
395   /**
396    * Returns a list of owned monitors. VM must support the
397    * canGetOwnedMonitorInfo capability.
398    *
399    * @param thread a thread
400    * @returns the list of monitors owned by this thread
401    */
getOwnedMonitors(Thread thread)402   public static native Object[] getOwnedMonitors(Thread thread)
403     throws JdwpException;
404 
405   /**
406    * Returns the current contended monitor for a thread. VM must
407    * support canGetCurrentContendedMonitor capability.
408    *
409    * @param thread the thread
410    * @returns the contended monitor
411    */
getCurrentContendedMonitor(Thread thread)412   public static native Object getCurrentContendedMonitor(Thread thread)
413     throws JdwpException;
414 
415   /**
416    * Pop all frames up to and including the given frame. VM must
417    * support canPopFrames capability. It is the responsibility
418    * of the VM to check if the thread is suspended. If it is not,
419    * the VM should throw ThreadNotSuspendedException.
420    *
421    * @param thread the thread
422    * @param frame the frame ID
423    */
popFrames(Thread thread, long frameId)424   public static native void popFrames(Thread thread, long frameId);
425 }
426