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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [gnu/] [classpath/] [jdwp/] [VMIdManager.java] - Blame information for rev 756

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 756 jeremybenn
/* VMIdManager.java -- A reference/example implementation of a manager for
2
   JDWP object/reference type IDs
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.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.nio.ByteBuffer;
52
import java.util.HashMap;
53
import java.util.Hashtable;
54
 
55
/**
56
 * This class manages objects and referencetypes that are reported
57
 * to the debugger. All objects and referencetypes reported to the
58
 * debugger should go through this manager.
59
 *
60
 * A brief summary of what an <code>IdManager</code> must provide:
61
 *
62
 * <code>
63
 * public ObjectId getObjectId (Object theObject);
64
 * public ObjectId get (long id);
65
 * public ObjectId readObjectId (ByteBuffer bb);
66
 * public ReferenceTypeId getReferenceTypeId (Class clazz);
67
 * public ReferenceTypeId getReferenceType (long id);
68
 * public ReferenceTypeId readReferenceTypeId (ByteBuffer bb);
69
 * </code>
70
 *
71
 * See the javadoc on these methods later in this file for more
72
 * information on these functions.
73
 *
74
 * <b>NOTE:</b> All IDs handled by the ID manager (all object and reference
75
 * type IDs) are assumed to be of type <code>long</code>.
76
 *
77
 * <b>NOTE:</b> This class does not manage virtual machine-specific types,
78
 * like methods, fields, and frames. These already have unique IDs within
79
 * the virtual machine and do not need further abstraction here.
80
 *
81
 * @author Keith Seitz  (keiths@redhat.com)
82
 */
83
public class VMIdManager
84
{
85
  // This factory generates ids for objects and types that may
86
  // be sent to a debugger.
87
  private static class IdFactory
88
  {
89
    // ID of last object / referencetype
90
    private static Object _idLock = new Object ();
91
    private static Object _ridLock = new Object ();
92
    private static long _lastId = 0;
93
    private static long _lastRid = 0;
94
 
95
    // A list of all ID types
96
    private static HashMap _idList = new HashMap ();
97
 
98
    // Initialize the id list with known types
99
    static
100
    {
101
      // ObjectId and ArrayId are special cases. See newObjectId.
102
      _idList.put (ClassLoaderId.typeClass, ClassLoaderId.class);
103
      _idList.put (ClassObjectId.typeClass, ClassObjectId.class);
104
      _idList.put (StringId.typeClass, StringId.class);
105
      _idList.put (ThreadId.typeClass, ThreadId.class);
106
      _idList.put (ThreadGroupId.typeClass, ThreadGroupId.class);
107
    }
108
 
109
    /**
110
     * Returns a new id for the given object
111
     *
112
     * @param obj  SoftReference of the object for which an id is desired
113
     * @returns a suitable object id
114
     */
115
    public static ObjectId newObjectId (SoftReference obj)
116
    {
117
      ObjectId id = null;
118
      Object object = obj.get ();
119
 
120
      // Special case: arrays
121
      if (object.getClass ().isArray ())
122
        id = new ArrayId ();
123
      else
124
        {
125
          // Loop through all classes until we hit baseclass
126
          Class myClass;
127
          for (myClass = object.getClass (); myClass != null;
128
               myClass = myClass.getSuperclass ())
129
            {
130
              Class clz = (Class) _idList.get (myClass);
131
              if (clz != null)
132
                {
133
                  try
134
                    {
135
                      id = (ObjectId) clz.newInstance ();
136
                      synchronized (_idLock)
137
                        {
138
                          id.setId (++_lastId);
139
                        }
140
                      id.setReference (obj);
141
                      return id;
142
                    }
143
                  catch (InstantiationException ie)
144
                    {
145
                      // This really should not happen
146
                      throw new RuntimeException ("cannot create new ID", ie);
147
                    }
148
                  catch (IllegalAccessException iae)
149
                    {
150
                      // This really should not happen
151
                      throw new RuntimeException ("illegal access of ID", iae);
152
                    }
153
                }
154
            }
155
 
156
          /* getSuperclass returned null and no matching ID type found.
157
             So it must derive from Object. */
158
          id = new ObjectId ();
159
        }
160
 
161
      synchronized (_idLock)
162
        {
163
          id.setId (++_lastId);
164
        }
165
      id.setReference (obj);
166
      return id;
167
    }
168
 
169
    /**
170
     * Returns a new reference type id for the given class
171
     *
172
     * @param ref  SoftReference to the desired type
173
     * @returns a suitable reference type id or null when the
174
     * reference is cleared.
175
     */
176
    public static ReferenceTypeId newReferenceTypeId (SoftReference ref)
177
    {
178
      ReferenceTypeId id;
179
      Class clazz = (Class) ref.get ();
180
      if (clazz == null)
181
        return null;
182
 
183
      if (clazz.isArray ())
184
        id = new ArrayReferenceTypeId ();
185
      else if (clazz.isInterface ())
186
        id = new InterfaceReferenceTypeId ();
187
      else
188
        id = new ClassReferenceTypeId ();
189
      id.setReference (ref);
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
    // Special case: null object.
341
    if (theObject == null)
342
      return new NullObjectId ();
343
 
344
    ReferenceKey ref = new ReferenceKey (theObject, _refQueue);
345
    ObjectId id = (ObjectId) _oidTable.get (ref);
346
    if (id == null)
347
      {
348
        // update the tables -- this is an arbitrary place to put this
349
        _update ();
350
 
351
        // Object not found. Make new id for it
352
        id = IdFactory.newObjectId (ref);
353
        _oidTable.put (ref, id);
354
        _idTable.put (new Long (id.getId ()), id);
355
      }
356
 
357
    return id;
358
  }
359
 
360
  /**
361
   * Returns the <code>JdwpId</code> for a given ID. Unlike
362
   * <code>getId</code>, it throws an exception if the ID is not
363
   * known.
364
   *
365
   * @param id  the numerical ID of the desired <code>JdwpId</code>
366
   * @throws InvalidObjectException if the ID is not found
367
   */
368
  public ObjectId get (long id)
369
    throws InvalidObjectException
370
  {
371
    // Special case: null object id.
372
    if (id == 0)
373
      return new NullObjectId ();
374
 
375
    ObjectId oid = (ObjectId) _idTable.get (new Long (id));
376
    if (oid == null)
377
      throw new InvalidObjectException (id);
378
 
379
    return oid;
380
  }
381
 
382
  public ObjectId readObjectId (ByteBuffer bb)
383
    throws InvalidObjectException
384
  {
385
    long id = bb.getLong ();
386
    return get (id);
387
  }
388
 
389
  /**
390
   * Gets the reference type id for the given class, creating
391
   * a new one if it does not already have an id
392
   *
393
   * @param clazz  the class for which to get an ID
394
   * @returns  the ID of the class
395
   */
396
  public ReferenceTypeId getReferenceTypeId (Class clazz)
397
  {
398
    ReferenceKey ref = new ReferenceKey (clazz);
399
    ReferenceTypeId id = (ReferenceTypeId)_classTable.get (ref);
400
    if (id == null)
401
      {
402
        // Object not found. Make new id for it
403
        id = IdFactory.newReferenceTypeId (ref);
404
        _classTable.put (ref, id);
405
        _ridTable.put (new Long (id.getId ()), id);
406
      }
407
 
408
    return id;
409
  }
410
 
411
  /**
412
   * Returns the <code>ReferenceTypeId</code> for a given ID. Unlike
413
   * <code>getReferenceTypeId</code>, it throws an exception if the ID is not
414
   * known.
415
   *
416
   * @param id  the numerical ID of the desired reference type
417
   * @throws InvalidClassException if the ID is not found
418
   */
419
  public ReferenceTypeId getReferenceType (long id)
420
    throws InvalidClassException
421
  {
422
    ReferenceTypeId rid = (ReferenceTypeId) _ridTable.get (new Long (id));
423
    if (rid == null)
424
      throw new InvalidClassException (id);
425
 
426
    return rid;
427
  }
428
 
429
  public ReferenceTypeId readReferenceTypeId (ByteBuffer bb)
430
    throws InvalidClassException
431
  {
432
    long id = bb.getLong ();
433
    return getReferenceType (id);
434
  }
435
}

powered by: WebSVN 2.1.0

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