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