OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [gnu/] [classpath/] [jdwp/] [VMIdManager.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* VMIdManager.java -- A reference/example implementation of a manager for
2
   JDWP object/reference type IDs
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.exception.InvalidClassException;
45
import gnu.classpath.jdwp.exception.InvalidObjectException;
46
import gnu.classpath.jdwp.id.*;
47
 
48
import java.lang.ref.Reference;
49
import java.lang.ref.ReferenceQueue;
50
import java.lang.ref.SoftReference;
51
import java.io.IOException;
52
import java.nio.ByteBuffer;
53
import java.util.HashMap;
54
import java.util.Hashtable;
55
import java.util.Iterator;
56
 
57
/**
58
 * This class manages objects and referencetypes that are reported
59
 * to the debugger. All objects and referencetypes reported to the
60
 * debugger should go through this manager.
61
 *
62
 * A brief summary of what an <code>IdManager</code> must provide:
63
 *
64
 * <code>
65
 * public ObjectId getObjectId (Object theObject);
66
 * public ObjectId get (long id);
67
 * public ObjectId readObjectId (ByteBuffer bb);
68
 * public ReferenceTypeId getReferenceTypeId (Class clazz);
69
 * public ReferenceTypeId getReferenceType (long id);
70
 * public ReferenceTypeId readReferenceTypeId (ByteBuffer bb);
71
 * </code>
72
 *
73
 * See the javadoc on these methods later in this file for more
74
 * information on these functions.
75
 *
76
 * <b>NOTE:</b> All IDs handled by the ID manager (all object and reference
77
 * type IDs) are assumed to be of type <code>long</code>.
78
 *
79
 * @author Keith Seitz  (keiths@redhat.com)
80
 */
81
public class VMIdManager
82
{
83
  // This factory generates ids for objects and types that may
84
  // be sent to a debugger.
85
  private static class IdFactory
86
  {
87
    // ID of last object / referencetype
88
    private static Object _idLock = new Object ();
89
    private static Object _ridLock = new Object ();
90
    private static long _lastId = 0;
91
    private static long _lastRid = 0;
92
 
93
    // A list of all ID types
94
    private static HashMap _idList = new HashMap ();
95
 
96
    // Initialize the id list with known types
97
    static
98
    {
99
      // ObjectId and ArrayId are special cases. See newObjectId.
100
      _idList.put (ClassLoaderId.typeClass, ClassLoaderId.class);
101
      _idList.put (ClassObjectId.typeClass, ClassObjectId.class);
102
      //_idList.put (FieldId.typeClass, FieldId.class);
103
      //_idList.put (FrameId.typeClass, FrameId.class);
104
      //_idList.put (MethodId.typeClass, MethodId.class);
105
      _idList.put (StringId.typeClass, StringId.class);
106
      _idList.put (ThreadId.typeClass, ThreadId.class);
107
      _idList.put (ThreadGroupId.typeClass, ThreadGroupId.class);
108
    }
109
 
110
    /**
111
     * Returns a new id for the given object
112
     *
113
     * @param object  the object for which an id is desired
114
     * @returns a suitable object id
115
     */
116
    public static ObjectId newObjectId (SoftReference obj)
117
    {
118
      ObjectId id = null;
119
      Object object = obj.get ();
120
 
121
      // Special case: arrays
122
      if (object.getClass ().isArray ())
123
        id = new ArrayId ();
124
      else
125
        {
126
          // Loop through all classes until we hit baseclass
127
          Class myClass;
128
          for (myClass = object.getClass (); myClass != null;
129
               myClass = myClass.getSuperclass ())
130
            {
131
              Class clz = (Class) _idList.get (myClass);
132
              if (clz != null)
133
                {
134
                  try
135
                    {
136
                      id = (ObjectId) clz.newInstance ();
137
                      synchronized (_idLock)
138
                        {
139
                          id.setId (++_lastId);
140
                        }
141
                      id.setReference (obj);
142
                      return id;
143
                    }
144
                  catch (InstantiationException ie)
145
                    {
146
                      // This really should not happen
147
                      throw new RuntimeException ("cannot create new ID", ie);
148
                    }
149
                  catch (IllegalAccessException iae)
150
                    {
151
                      // This really should not happen
152
                      throw new RuntimeException ("illegal access of ID", iae);
153
                    }
154
                }
155
            }
156
 
157
          /* getSuperclass returned null and no matching ID type found.
158
             So it must derive from Object. */
159
          id = new ObjectId ();
160
        }
161
 
162
      synchronized (_idLock)
163
        {
164
          id.setId (++_lastId);
165
        }
166
      id.setReference (obj);
167
      return id;
168
    }
169
 
170
    /**
171
     * Returns a new reference type id for the given class
172
     *
173
     * @param clazz  the <code>Class</code> for which an id is desired
174
     * @returns a suitable reference type id or null when the
175
     * reference is cleared.
176
     */
177
    public static ReferenceTypeId newReferenceTypeId (SoftReference ref)
178
    {
179
      ReferenceTypeId id;
180
      Class clazz = (Class) ref.get ();
181
      if (clazz == null)
182
        return null;
183
 
184
      if (clazz.isArray ())
185
        id = new ArrayReferenceTypeId ();
186
      else if (clazz.isInterface ())
187
        id = new InterfaceReferenceTypeId ();
188
      else
189
        id = new ClassReferenceTypeId ();
190
      synchronized (_ridLock)
191
        {
192
          id.setId (++_lastRid);
193
        }
194
      return id;
195
    }
196
  }
197
 
198
  /**
199
   * This class is a SoftReferenceIdentity type that is used by
200
   * the ID manager.
201
   */
202
  class ReferenceKey extends SoftReference
203
  {
204
    // Hash code of referent
205
    private int _hash;
206
 
207
    /**
208
     * Constructs a new <code>ReferenceKey</code> object
209
     * with the given referent.
210
     *
211
     * <p>This constructor should only be used for object lookups
212
     * by the backend.
213
     *
214
     * @param referent  the object to reference
215
     */
216
    public ReferenceKey (Object referent)
217
    {
218
      super (referent);
219
      _hash = referent.hashCode ();
220
    }
221
 
222
    /**
223
     * Constructs a new <code>ReferenceKey</code> object
224
     * with the given referent and reference queue.
225
     *
226
     * <p>The JDWP back-end stores a <code>ReferenceKey</code>
227
     * with its corresponding <code>JdwpId</code>. This constructor
228
     * is used by the back-end when adding new IDs to be managed.
229
     *
230
     * @param referent  the object to reference
231
     * @param queue     the queue to which to report garbage collections
232
     */
233
    public ReferenceKey (Object referent, ReferenceQueue queue)
234
    {
235
      super (referent, queue);
236
      _hash = referent.hashCode ();
237
    }
238
 
239
    /**
240
     * Returns the hash code of the referent.
241
     * This seems hacky, but is required in order to use this class
242
     * as a hash table key.
243
     *
244
     * @returns the hash code of the referent
245
     */
246
    public int hashCode ()
247
    {
248
      return _hash;
249
    }
250
 
251
    /**
252
     * Comparator for keys
253
     *
254
     * This method can be used in two ways:
255
     *
256
     * <ol>
257
     *    <li>For table lookups, where we want to compare referents</li>
258
     *    <li>For clearing GCd objects, where we want to compare the actual
259
     *        key object (not the referent)</li>
260
     * </ol>
261
     */
262
    public boolean equals (Object obj)
263
    {
264
      if (obj instanceof ReferenceKey)
265
        {
266
          ReferenceKey ref = (ReferenceKey) obj;
267
 
268
          /* First check if the two references are the same.
269
             If they are, that means we must be clearing GCd objects. */
270
          if (this == obj)
271
            return true;
272
 
273
          return (ref.get () == get ());
274
        }
275
 
276
      return false;
277
    }
278
  }
279
 
280
  // instance of VMIdManager
281
  private static VMIdManager _idm = new VMIdManager ();
282
 
283
  // A reference queue for our objects
284
  private ReferenceQueue _refQueue;
285
 
286
  // Mapping of objects (ReferenceKey) to IDs (ObjectId)
287
  private Hashtable _oidTable;
288
 
289
  // Mapping of ID numbers (Long) to IDs (ObjectId)
290
  private Hashtable _idTable;
291
 
292
  /* Mapping of class (ReferenceKey) to IDs (ReferenceTypeId) for reference
293
     types. Unlike other types, reference id types are NEVER released. */
294
  private Hashtable _classTable;
295
 
296
  // Mapping of ID numbers (Long) to reference type IDs (ReferenceTypeId)
297
  private Hashtable _ridTable;
298
 
299
  /**
300
   * Gets the instance of VMIdManager, constructing a new one
301
   * if none currently exists.
302
   */
303
  public static VMIdManager getDefault ()
304
  {
305
    return _idm;
306
  }
307
 
308
  // Constructs a new <code>IdManager</code>
309
  private VMIdManager ()
310
  {
311
    _refQueue = new ReferenceQueue ();
312
    _oidTable = new Hashtable (50);
313
    _idTable = new Hashtable (50);
314
    _classTable = new Hashtable (20);
315
    _ridTable = new Hashtable (20);
316
  }
317
 
318
  // Updates the object ID table, removing IDs whose objects have
319
  // been garbage collected.
320
  private void _update ()
321
  {
322
    Reference ref;
323
    while ((ref = _refQueue.poll ()) != null)
324
      {
325
        ObjectId id = (ObjectId) _oidTable.get (ref);
326
        _oidTable.remove (ref);
327
        _idTable.remove (new Long (id.getId ()));
328
      }
329
  }
330
 
331
  /**
332
   * Returns an id for the given object, adding it
333
   * if it does not have an id.
334
   *
335
   * @param theObject  the object to get an ID/add
336
   * @returns  the ID of the object
337
   */
338
  public ObjectId getObjectId (Object theObject)
339
  {
340
    ReferenceKey ref = new ReferenceKey (theObject, _refQueue);
341
    ObjectId id = (ObjectId) _oidTable.get (ref);
342
    if (id == null)
343
      {
344
        // update the tables -- this is an arbitrary place to put this
345
        _update ();
346
 
347
        // Object not found. Make new id for it
348
        id = IdFactory.newObjectId (ref);
349
        _oidTable.put (ref, id);
350
        _idTable.put (new Long (id.getId ()), id);
351
      }
352
 
353
    return id;
354
  }
355
 
356
  /**
357
   * Returns the <code>JdwpId</code> for a given ID. Unlike
358
   * <code>getId</code>, it throws an exception if the ID is not
359
   * known.
360
   *
361
   * @param id  the numerical ID of the desired <code>JdwpId</code>
362
   * @throws InvalidObjectException if the ID is not found
363
   */
364
  public ObjectId get (long id)
365
    throws InvalidObjectException
366
  {
367
    ObjectId oid = (ObjectId) _idTable.get (new Long (id));
368
    if (oid == null)
369
      throw new InvalidObjectException (id);
370
 
371
    return oid;
372
  }
373
 
374
  public ObjectId readObjectId (ByteBuffer bb)
375
    throws InvalidObjectException
376
  {
377
    long id = bb.getLong ();
378
    return get (id);
379
  }
380
 
381
  /**
382
   * Gets the reference type id for the given class, creating
383
   * a new one if it does not already have an id
384
   *
385
   * @param clazz  the class for which to get an ID
386
   * @returns  the ID of the class
387
   */
388
  public ReferenceTypeId getReferenceTypeId (Class clazz)
389
  {
390
    ReferenceKey ref = new ReferenceKey (clazz);
391
    ReferenceTypeId id = (ReferenceTypeId)_classTable.get (ref);
392
    if (id == null)
393
      {
394
        // Object not found. Make new id for it
395
        id = IdFactory.newReferenceTypeId (ref);
396
        _classTable.put (ref, id);
397
        _ridTable.put (new Long (id.getId ()), id);
398
      }
399
 
400
    return id;
401
  }
402
 
403
  /**
404
   * Returns the <code>ReferenceTypeId</code> for a given ID. Unlike
405
   * <code>getReferenceTypeId</code>, it throws an exception if the ID is not
406
   * known.
407
   *
408
   * @param id  the numerical ID of the desired reference type
409
   * @throws InvalidClassException if the ID is not found
410
   */
411
  public ReferenceTypeId getReferenceType (long id)
412
    throws InvalidClassException
413
  {
414
    ReferenceTypeId rid = (ReferenceTypeId) _ridTable.get (new Long (id));
415
    if (rid == null)
416
      throw new InvalidClassException (id);
417
 
418
    return rid;
419
  }
420
 
421
  public ReferenceTypeId readReferenceTypeId (ByteBuffer bb)
422
    throws InvalidClassException
423
  {
424
    long id = bb.getLong ();
425
    return getReferenceType (id);
426
  }
427
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.