1 /* VMVirtualMachine.java -- A reference implementation of a JDWP virtual
2    machine
3 
4    Copyright (C) 2005 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.InvalidClassException;
46 import gnu.classpath.jdwp.exception.InvalidObjectException;
47 import gnu.classpath.jdwp.id.ObjectId;
48 import gnu.classpath.jdwp.id.ReferenceTypeId;
49 import gnu.classpath.jdwp.util.LineTable;
50 import gnu.classpath.jdwp.util.MethodResult;
51 import gnu.classpath.jdwp.util.VariableTable;
52 
53 import java.io.IOException;
54 import java.lang.reflect.Method;
55 import java.nio.ByteBuffer;
56 import java.util.ArrayList;
57 import java.util.Iterator;
58 
59 /**
60  * A virtual machine according to JDWP.
61  *
62  * @author Keith Seitz  <keiths@redhat.com>
63  */
64 public class VMVirtualMachine
65 {
66   /**
67    * Suspend a thread
68    *
69    * @param  thread  the thread to suspend
70    */
suspendThread(Thread thread)71   public static native void suspendThread (Thread thread);
72 
73   /**
74    * Suspend all threads
75    */
suspendAllThreads()76   public static void suspendAllThreads ()
77   {
78     // Our JDWP thread group -- don't suspend any of those threads
79     Thread current = Thread.currentThread ();
80     ThreadGroup jdwpGroup = current.getThreadGroup ();
81 
82     // Find the root ThreadGroup
83     ThreadGroup group = jdwpGroup;
84     ThreadGroup parent = group.getParent ();
85     while (parent != null)
86       {
87 	group = parent;
88 	parent = group.getParent ();
89       }
90 
91     // Get all the threads in the system
92     int num = group.activeCount ();
93     Thread[] threads = new Thread[num];
94     group.enumerate (threads);
95 
96     for (int i = 0; i < num; ++i)
97       {
98 	Thread t = threads[i];
99 	if (t != null)
100 	  {
101 	    if (t.getThreadGroup () == jdwpGroup || t == current)
102 	      {
103 		// Don't suspend the current thread or any JDWP thread
104 		continue;
105 	      }
106 	    else
107 	      suspendThread (t);
108 	  }
109       }
110 
111     // Now suspend the current thread
112     suspendThread (current);
113   }
114 
115   /**
116    * Resume a thread. A thread must be resumed as many times
117    * as it has been suspended.
118    *
119    * @param  thread  the thread to resume
120    */
resumeThread(Thread thread)121   public static native void resumeThread (Thread thread);
122 
123   /**
124    * Resume all threads. This simply decrements the thread's
125    * suspend count. It can not be used to force the application
126    * to run.
127    */
resumeAllThreads()128   public static void resumeAllThreads ()
129   {
130     // Our JDWP thread group -- don't resume
131     Thread current = Thread.currentThread ();
132     ThreadGroup jdwpGroup = current.getThreadGroup ();
133 
134     // Find the root ThreadGroup
135     ThreadGroup group = jdwpGroup;
136     ThreadGroup parent = group.getParent ();
137     while (parent != null)
138       {
139 	group = parent;
140 	parent = group.getParent ();
141       }
142 
143     // Get all the threads in the system
144     int num = group.activeCount ();
145     Thread[] threads = new Thread[num];
146     group.enumerate (threads);
147 
148     for (int i = 0; i < num; ++i)
149       {
150 	Thread t = threads[i];
151 	if (t != null)
152 	  {
153 	    if (t.getThreadGroup () == jdwpGroup || t == current)
154 	      {
155 		// Don't resume the current thread or any JDWP thread
156 		continue;
157 	      }
158 	    else
159 	      resumeThread (t);
160 	  }
161       }
162   }
163 
164   /**
165    * Get the suspend count for a give thread
166    *
167    * @param  thread  the thread whose suspend count is desired
168    * @return the number of times the thread has been suspended
169    */
getSuspendCount(Thread thread)170   public static native int getSuspendCount (Thread thread);
171 
172   /**
173    * Returns a count of the number of loaded classes in the VM
174    */
getAllLoadedClassesCount()175   public static native int getAllLoadedClassesCount ();
176 
177   /**
178    * Returns an iterator over all the loaded classes in the VM
179    */
getAllLoadedClasses()180   public static native Iterator getAllLoadedClasses ();
181 
182   /**
183    * Returns the status of the given class
184    *
185    * @param  clazz  the class whose status is desired
186    * @return a flag containing the class's status
187    * @see JdwpConstants.ClassStatus
188    */
getClassStatus(Class clazz)189   public static native int getClassStatus (Class clazz);
190 
191 
192   /**
193    * Returns the thread's call stack
194    *
195    * @param  thread  thread for which to get call stack
196    * @param  start   index of first frame to return
197    * @param  length  number of frames to return (-1 for all frames)
198    * @return a list of frames
199    */
getFrames(Thread thread, int strart, int length)200   public static native ArrayList getFrames (Thread thread, int strart,
201 					    int length);
202 
203   /**
204    * Returns the frame for a given thread with the frame ID in
205    * the buffer
206    *
207    * I don't like this.
208    *
209    * @param  thread  the frame's thread
210    * @param  bb      buffer containing the frame's ID
211    * @return the desired frame
212    */
getFrame(Thread thread, ByteBuffer bb)213   public static native VMFrame getFrame (Thread thread, ByteBuffer bb);
214 
215   /**
216    * Returns the number of frames in the thread's stack
217    *
218    * @param  thread  the thread for which to get a frame count
219    * @return the number of frames in the thread's stack
220    */
getFrameCount(Thread thread)221   public static native int getFrameCount (Thread thread);
222 
223 
224   /**
225    * Returns the status of a thread
226    *
227    * @param  thread  the thread for which to get status
228    * @return integer status of the thread
229    * @see JdwpConstants.ThreadStatus
230    */
getThreadStatus(Thread thread)231   public static native int getThreadStatus (Thread thread);
232 
233   /**
234    * Returns a list of all classes which this class loader has been
235    * requested to load
236    *
237    * @param  cl  the class loader
238    * @return a list of all visible classes
239    */
getLoadRequests(ClassLoader cl)240   public static native ArrayList getLoadRequests (ClassLoader cl);
241 
242   /**
243    * Executes a method in the virtual machine
244    *
245    * @param  obj         instance in which to invoke method (null for static)
246    * @param  thread      the thread in which to invoke the method
247    * @param  clazz       the class in which the method is defined
248    * @param  method      the method to invoke
249    * @param  values      arguments to pass to method
250    * @param  nonVirtual  "otherwise, normal virtual invoke
251    *                     (instance methods only) "
252    * @return a result object containing the results of the invocation
253    */
executeMethod(Object obj, Thread thread, Class clazz, Method method, Object[] values, boolean nonVirtual)254   public static native MethodResult executeMethod (Object obj, Thread thread,
255 					    Class clazz, Method method,
256 					    Object[] values,
257 					    boolean nonVirtual);
258 
259   /**
260    * "Returns variable information for the method. The variable table
261    * includes arguments and locals declared within the method. For instance
262    * methods, the "this" reference is included in the table. Also, synthetic
263    * variables may be present."
264    *
265    * @param  clazz   the class in which the method is defined
266    * @param  method  the method for which variable information is desired
267    * @return a result object containing the information
268    */
getVarTable(Class clazz, Method method)269   public static native VariableTable getVarTable (Class clazz, Method method);
270 
271   /**
272    * "Returns line number information for the method, if present. The line
273    * table maps source line numbers to the initial code index of the line.
274    * The line table is ordered by code index (from lowest to highest). The
275    * line number information is constant unless a new class definition is
276    * installed using RedefineClasses."
277    *
278    * @param  clazz   the class in which the method is defined
279    * @param  method  the method whose line table is desired
280    * @return a result object containing the line table
281    */
getLineTable(Class clazz, Method method)282   public static native LineTable getLineTable (Class clazz, Method method);
283 
284   /**
285    * "Returns the name of source file in which a reference type was declared"
286    *
287    * @param  clazz  the class for which to return a source file
288    * @return a string containing the source file name; "no path information
289    *         for the file is included"
290    */
getSourceFile(Class clazz)291   public static native String getSourceFile (Class clazz);
292 
293   /**
294    * Register a request from the debugger
295    *
296    * Virtual machines have two options. Either do nothing and allow
297    * the event manager to take care of the request (useful for broadcast-type
298    * events like class prepare/load/unload, thread start/end, etc.)
299    * or do some internal work to set up the event notification (useful for
300    * execution-related events like breakpoints, single-stepping, etc.).
301    */
registerEvent(EventRequest request)302   public static native void registerEvent (EventRequest request);
303 
304   /**
305    * Unregisters the given request
306    *
307    * @param  request  the request to unregister
308    */
unregisterEvent(EventRequest request)309   public static native void unregisterEvent (EventRequest request);
310 
311 
312   /**
313    * Clear all events of the given kind
314    *
315    * @param  kind  the type of events to clear
316    */
clearEvents(byte kind)317   public static native void clearEvents (byte kind);
318 }
319