comparison agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 package sun.jvm.hotspot.jdi;
26
27 import com.sun.jdi.*;
28 import com.sun.jdi.event.EventQueue;
29 import com.sun.jdi.request.EventRequestManager;
30
31 import sun.jvm.hotspot.HotSpotAgent;
32 import sun.jvm.hotspot.types.TypeDataBase;
33 import sun.jvm.hotspot.oops.Klass;
34 import sun.jvm.hotspot.oops.InstanceKlass;
35 import sun.jvm.hotspot.oops.ArrayKlass;
36 import sun.jvm.hotspot.oops.ObjArrayKlass;
37 import sun.jvm.hotspot.oops.TypeArrayKlass;
38 import sun.jvm.hotspot.oops.Oop;
39 import sun.jvm.hotspot.oops.Instance;
40 import sun.jvm.hotspot.oops.Array;
41 import sun.jvm.hotspot.oops.ObjArray;
42 import sun.jvm.hotspot.oops.TypeArray;
43 import sun.jvm.hotspot.oops.Symbol;
44 import sun.jvm.hotspot.oops.ObjectHeap;
45 import sun.jvm.hotspot.oops.DefaultHeapVisitor;
46 import sun.jvm.hotspot.oops.JVMDIClassStatus;
47 import sun.jvm.hotspot.runtime.VM;
48 import sun.jvm.hotspot.runtime.JavaThread;
49 import sun.jvm.hotspot.memory.SystemDictionary;
50 import sun.jvm.hotspot.memory.SymbolTable;
51 import sun.jvm.hotspot.memory.Universe;
52 import sun.jvm.hotspot.utilities.Assert;
53
54 import java.util.List;
55 import java.util.ArrayList;
56 import java.util.Map;
57 import java.util.Iterator;
58 import java.util.Collections;
59 import java.util.HashMap;
60 import java.util.Observer;
61 import java.util.StringTokenizer;
62 import java.lang.ref.SoftReference;
63 import java.lang.ref.ReferenceQueue;
64 import java.lang.ref.Reference;
65
66 public class VirtualMachineImpl extends MirrorImpl implements PathSearchingVirtualMachine {
67
68 private HotSpotAgent saAgent = new HotSpotAgent();
69 private VM saVM;
70 private Universe saUniverse;
71 private SystemDictionary saSystemDictionary;
72 private SymbolTable saSymbolTable;
73 private ObjectHeap saObjectHeap;
74
75 VM saVM() {
76 return saVM;
77 }
78
79 SystemDictionary saSystemDictionary() {
80 return saSystemDictionary;
81 }
82
83 SymbolTable saSymbolTable() {
84 return saSymbolTable;
85 }
86
87 Universe saUniverse() {
88 return saUniverse;
89 }
90
91 ObjectHeap saObjectHeap() {
92 return saObjectHeap;
93 }
94
95 com.sun.jdi.VirtualMachineManager vmmgr;
96
97 private final ThreadGroup threadGroupForJDI;
98
99 // Per-vm singletons for primitive types and for void.
100 // singleton-ness protected by "synchronized(this)".
101 private BooleanType theBooleanType;
102 private ByteType theByteType;
103 private CharType theCharType;
104 private ShortType theShortType;
105 private IntegerType theIntegerType;
106 private LongType theLongType;
107 private FloatType theFloatType;
108 private DoubleType theDoubleType;
109
110 private VoidType theVoidType;
111
112 private VoidValue voidVal;
113 private Map typesByID; // Map<Klass, ReferenceTypeImpl>
114 private List typesBySignature; // List<ReferenceTypeImpl> - used in signature search
115 private boolean retrievedAllTypes = false;
116 private List bootstrapClasses; // all bootstrap classes
117 private ArrayList allThreads;
118 private ArrayList topLevelGroups;
119 final int sequenceNumber;
120
121 // ObjectReference cache
122 // "objectsByID" protected by "synchronized(this)".
123 private final Map objectsByID = new HashMap();
124 private final ReferenceQueue referenceQueue = new ReferenceQueue();
125
126 // names of some well-known classes to jdi
127 private Symbol javaLangString;
128 private Symbol javaLangThread;
129 private Symbol javaLangThreadGroup;
130 private Symbol javaLangClass;
131 private Symbol javaLangClassLoader;
132
133 // used in ReferenceTypeImpl.isThrowableBacktraceField
134 private Symbol javaLangThrowable;
135
136 // names of classes used in array assignment check
137 // refer to ArrayTypeImpl.isAssignableTo
138 private Symbol javaLangObject;
139 private Symbol javaLangCloneable;
140 private Symbol javaIoSerializable;
141
142 // symbol used in ClassTypeImpl.isEnum check
143 private Symbol javaLangEnum;
144
145 Symbol javaLangObject() {
146 return javaLangObject;
147 }
148
149 Symbol javaLangCloneable() {
150 return javaLangCloneable;
151 }
152
153 Symbol javaIoSerializable() {
154 return javaIoSerializable;
155 }
156
157 Symbol javaLangEnum() {
158 return javaLangEnum;
159 }
160
161 Symbol javaLangThrowable() {
162 return javaLangThrowable;
163 }
164
165 // name of the current default stratum
166 private String defaultStratum;
167
168 // initialize known class name symbols
169 private void initClassNameSymbols() {
170 SymbolTable st = saSymbolTable();
171 javaLangString = st.probe("java/lang/String");
172 javaLangThread = st.probe("java/lang/Thread");
173 javaLangThreadGroup = st.probe("java/lang/ThreadGroup");
174 javaLangClass = st.probe("java/lang/Class");
175 javaLangClassLoader = st.probe("java/lang/ClassLoader");
176 javaLangThrowable = st.probe("java/lang/Throwable");
177 javaLangObject = st.probe("java/lang/Object");
178 javaLangCloneable = st.probe("java/lang/Cloneable");
179 javaIoSerializable = st.probe("java/io/Serializable");
180 javaLangEnum = st.probe("java/lang/Enum");
181 }
182
183 private void init() {
184 saVM = VM.getVM();
185 saUniverse = saVM.getUniverse();
186 saSystemDictionary = saVM.getSystemDictionary();
187 saSymbolTable = saVM.getSymbolTable();
188 saObjectHeap = saVM.getObjectHeap();
189 initClassNameSymbols();
190 }
191
192 static public VirtualMachineImpl createVirtualMachineForCorefile(VirtualMachineManager mgr,
193 String javaExecutableName,
194 String coreFileName,
195 int sequenceNumber)
196 throws Exception {
197 if (Assert.ASSERTS_ENABLED) {
198 Assert.that(coreFileName != null, "SA VirtualMachineImpl: core filename = null is not yet implemented");
199 }
200 if (Assert.ASSERTS_ENABLED) {
201 Assert.that(javaExecutableName != null, "SA VirtualMachineImpl: java executable = null is not yet implemented");
202 }
203
204 VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber);
205 try {
206 myvm.saAgent.attach(javaExecutableName, coreFileName);
207 myvm.init();
208 } catch (Exception ee) {
209 myvm.saAgent.detach();
210 throw ee;
211 }
212 return myvm;
213 }
214
215 static public VirtualMachineImpl createVirtualMachineForPID(VirtualMachineManager mgr,
216 int pid,
217 int sequenceNumber)
218 throws Exception {
219
220 VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber);
221 try {
222 myvm.saAgent.attach(pid);
223 myvm.init();
224 } catch (Exception ee) {
225 myvm.saAgent.detach();
226 throw ee;
227 }
228 return myvm;
229 }
230
231 static public VirtualMachineImpl createVirtualMachineForServer(VirtualMachineManager mgr,
232 String server,
233 int sequenceNumber)
234 throws Exception {
235 if (Assert.ASSERTS_ENABLED) {
236 Assert.that(server != null, "SA VirtualMachineImpl: DebugServer = null is not yet implemented");
237 }
238
239 VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber);
240 try {
241 myvm.saAgent.attach(server);
242 myvm.init();
243 } catch (Exception ee) {
244 myvm.saAgent.detach();
245 throw ee;
246 }
247 return myvm;
248 }
249
250
251 VirtualMachineImpl(VirtualMachineManager mgr, int sequenceNumber)
252 throws Exception {
253 super(null); // Can't use super(this)
254 vm = this;
255
256 this.sequenceNumber = sequenceNumber;
257 this.vmmgr = mgr;
258
259 /* Create ThreadGroup to be used by all threads servicing
260 * this VM.
261 */
262 threadGroupForJDI = new ThreadGroup("JDI [" +
263 this.hashCode() + "]");
264
265 ((com.sun.tools.jdi.VirtualMachineManagerImpl)mgr).addVirtualMachine(this);
266
267 // By default SA agent classes prefer dbx debugger to proc debugger
268 // and Windows process debugger to windbg debugger. SA expects
269 // special properties to be set to choose other debuggers. We will set
270 // those here before attaching to SA agent.
271
272 System.setProperty("sun.jvm.hotspot.debugger.useProcDebugger", "true");
273 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true");
274 }
275
276 // we reflectively use newly spec'ed class because our ALT_BOOTDIR
277 // is 1.4.2 and not 1.5.
278 private static Class vmCannotBeModifiedExceptionClass = null;
279 void throwNotReadOnlyException(String operation) {
280 RuntimeException re = null;
281 if (vmCannotBeModifiedExceptionClass == null) {
282 try {
283 vmCannotBeModifiedExceptionClass = Class.forName("com.sun.jdi.VMCannotBeModifiedException");
284 } catch (ClassNotFoundException cnfe) {
285 vmCannotBeModifiedExceptionClass = UnsupportedOperationException.class;
286 }
287 }
288 try {
289 re = (RuntimeException) vmCannotBeModifiedExceptionClass.newInstance();
290 } catch (Exception exp) {
291 re = new RuntimeException(exp.getMessage());
292 }
293 throw re;
294 }
295
296 public boolean equals(Object obj) {
297 // Oh boy; big recursion troubles if we don't have this!
298 // See MirrorImpl.equals
299 return this == obj;
300 }
301
302 public int hashCode() {
303 // big recursion if we don't have this. See MirrorImpl.hashCode
304 return System.identityHashCode(this);
305 }
306
307 public List classesByName(String className) {
308 String signature = JNITypeParser.typeNameToSignature(className);
309 List list;
310 if (!retrievedAllTypes) {
311 retrieveAllClasses();
312 }
313 list = findReferenceTypes(signature);
314 return Collections.unmodifiableList(list);
315 }
316
317 public List allClasses() {
318 if (!retrievedAllTypes) {
319 retrieveAllClasses();
320 }
321 ArrayList a;
322 synchronized (this) {
323 a = new ArrayList(typesBySignature);
324 }
325 return Collections.unmodifiableList(a);
326 }
327
328 // classes loaded by bootstrap loader
329 List bootstrapClasses() {
330 if (bootstrapClasses == null) {
331 bootstrapClasses = new ArrayList();
332 List all = allClasses();
333 for (Iterator itr = all.iterator(); itr.hasNext();) {
334 ReferenceType type = (ReferenceType) itr.next();
335 if (type.classLoader() == null) {
336 bootstrapClasses.add(type);
337 }
338 }
339 }
340 return bootstrapClasses;
341 }
342
343 private synchronized List findReferenceTypes(String signature) {
344 if (typesByID == null) {
345 return new ArrayList(0);
346 }
347
348 // we haven't sorted types by signatures. But we can take
349 // advantage of comparing symbols instead of name. In the worst
350 // case, we will be comparing N addresses rather than N strings
351 // where N being total no. of classes in allClasses() list.
352
353 // The signature could be Lx/y/z; or [....
354 // If it is Lx/y/z; the internal type name is x/y/x
355 // for array klasses internal type name is same as
356 // signature
357 String typeName = null;
358 if (signature.charAt(0) == 'L') {
359 typeName = signature.substring(1, signature.length() - 1);
360 } else {
361 typeName = signature;
362 }
363
364 Symbol typeNameSym = saSymbolTable().probe(typeName);
365 // if there is no symbol in VM, then we wouldn't have that type
366 if (typeNameSym == null) {
367 return new ArrayList(0);
368 }
369
370 Iterator iter = typesBySignature.iterator();
371 List list = new ArrayList();
372 while (iter.hasNext()) {
373 // We have cached type name as symbol in reference type
374 ReferenceTypeImpl type = (ReferenceTypeImpl)iter.next();
375 if (typeNameSym.equals(type.typeNameAsSymbol())) {
376 list.add(type);
377 }
378 }
379 return list;
380 }
381
382 private void retrieveAllClasses() {
383 final List saKlasses = new ArrayList();
384 SystemDictionary.ClassVisitor visitor = new SystemDictionary.ClassVisitor() {
385 public void visit(Klass k) {
386 for (Klass l = k; l != null; l = l.arrayKlassOrNull()) {
387 // for non-array classes filter out un-prepared classes
388 // refer to 'allClasses' in share/back/VirtualMachineImpl.c
389 if (l instanceof ArrayKlass) {
390 saKlasses.add(l);
391 } else {
392 int status = l.getClassStatus();
393 if ((status & JVMDIClassStatus.PREPARED) != 0) {
394 saKlasses.add(l);
395 }
396 }
397 }
398 }
399 };
400
401 // refer to jvmtiGetLoadedClasses.cpp - getLoadedClasses in VM code.
402
403 // classes from SystemDictionary
404 saSystemDictionary.classesDo(visitor);
405
406 // From SystemDictionary we do not get primitive single
407 // dimensional array classes. add primitive single dimensional array
408 // klasses from Universe.
409 saVM.getUniverse().basicTypeClassesDo(visitor);
410
411 // Hold lock during processing to improve performance
412 // and to have safe check/set of retrievedAllTypes
413 synchronized (this) {
414 if (!retrievedAllTypes) {
415 // Number of classes
416 int count = saKlasses.size();
417 for (int ii = 0; ii < count; ii++) {
418 Klass kk = (Klass)saKlasses.get(ii);
419 ReferenceTypeImpl type = referenceType(kk);
420 }
421 retrievedAllTypes = true;
422 }
423 }
424 }
425
426 ReferenceTypeImpl referenceType(Klass kk) {
427 ReferenceTypeImpl retType = null;
428 synchronized (this) {
429 if (typesByID != null) {
430 retType = (ReferenceTypeImpl)typesByID.get(kk);
431 }
432 if (retType == null) {
433 retType = addReferenceType(kk);
434 }
435 }
436 return retType;
437 }
438
439 private void initReferenceTypes() {
440 typesByID = new HashMap();
441 typesBySignature = new ArrayList();
442 }
443
444 private synchronized ReferenceTypeImpl addReferenceType(Klass kk) {
445 if (typesByID == null) {
446 initReferenceTypes();
447 }
448 ReferenceTypeImpl newRefType = null;
449 if (kk instanceof ObjArrayKlass || kk instanceof TypeArrayKlass) {
450 newRefType = new ArrayTypeImpl(this, (ArrayKlass)kk);
451 } else if (kk instanceof InstanceKlass) {
452 if (kk.isInterface()) {
453 newRefType = new InterfaceTypeImpl(this, (InstanceKlass)kk);
454 } else {
455 newRefType = new ClassTypeImpl(this, (InstanceKlass)kk);
456 }
457 } else {
458 throw new RuntimeException("should not reach here");
459 }
460
461 typesByID.put(kk, newRefType);
462 typesBySignature.add(newRefType);
463 return newRefType;
464 }
465
466 ThreadGroup threadGroupForJDI() {
467 return threadGroupForJDI;
468 }
469
470 public void redefineClasses(Map classToBytes) {
471 throwNotReadOnlyException("VirtualMachineImpl.redefineClasses()");
472 }
473
474 private List getAllThreads() {
475 if (allThreads == null) {
476 allThreads = new ArrayList(10); // Might be enough, might not be
477 for (sun.jvm.hotspot.runtime.JavaThread thread =
478 saVM.getThreads().first(); thread != null;
479 thread = thread.next()) {
480 // refer to JvmtiEnv::GetAllThreads in jvmtiEnv.cpp.
481 // filter out the hidden-from-external-view threads.
482 if (thread.isHiddenFromExternalView() == false) {
483 ThreadReferenceImpl myThread = threadMirror(thread);
484 allThreads.add(myThread);
485 }
486 }
487 }
488 return allThreads;
489 }
490
491 public List allThreads() { //fixme jjh
492 return Collections.unmodifiableList(getAllThreads());
493 }
494
495 public void suspend() {
496 throwNotReadOnlyException("VirtualMachineImpl.suspend()");
497 }
498
499 public void resume() {
500 throwNotReadOnlyException("VirtualMachineImpl.resume()");
501 }
502
503 public List topLevelThreadGroups() { //fixme jjh
504 // The doc for ThreadGroup says that The top-level thread group
505 // is the only thread group whose parent is null. This means there is
506 // only one top level thread group. There will be a thread in this
507 // group so we will just find a thread whose threadgroup has no parent
508 // and that will be it.
509
510 if (topLevelGroups == null) {
511 topLevelGroups = new ArrayList(1);
512 Iterator myIt = getAllThreads().iterator();
513 while (myIt.hasNext()) {
514 ThreadReferenceImpl myThread = (ThreadReferenceImpl)myIt.next();
515 ThreadGroupReference myGroup = myThread.threadGroup();
516 ThreadGroupReference myParent = myGroup.parent();
517 if (myGroup.parent() == null) {
518 topLevelGroups.add(myGroup);
519 break;
520 }
521 }
522 }
523 return Collections.unmodifiableList(topLevelGroups);
524 }
525
526 public EventQueue eventQueue() {
527 throwNotReadOnlyException("VirtualMachine.eventQueue()");
528 return null;
529 }
530
531 public EventRequestManager eventRequestManager() {
532 throwNotReadOnlyException("VirtualMachineImpl.eventRequestManager()");
533 return null;
534 }
535
536 public BooleanValue mirrorOf(boolean value) {
537 return new BooleanValueImpl(this,value);
538 }
539
540 public ByteValue mirrorOf(byte value) {
541 return new ByteValueImpl(this,value);
542 }
543
544 public CharValue mirrorOf(char value) {
545 return new CharValueImpl(this,value);
546 }
547
548 public ShortValue mirrorOf(short value) {
549 return new ShortValueImpl(this,value);
550 }
551
552 public IntegerValue mirrorOf(int value) {
553 return new IntegerValueImpl(this,value);
554 }
555
556 public LongValue mirrorOf(long value) {
557 return new LongValueImpl(this,value);
558 }
559
560 public FloatValue mirrorOf(float value) {
561 return new FloatValueImpl(this,value);
562 }
563
564 public DoubleValue mirrorOf(double value) {
565 return new DoubleValueImpl(this,value);
566 }
567
568 public StringReference mirrorOf(String value) {
569 throwNotReadOnlyException("VirtualMachinestop.mirrorOf(String)");
570 return null;
571 }
572
573 public VoidValue mirrorOfVoid() {
574 if (voidVal == null) {
575 voidVal = new VoidValueImpl(this);
576 }
577 return voidVal;
578 }
579
580
581 public Process process() {
582 throwNotReadOnlyException("VirtualMachine.process");
583 return null;
584 }
585
586 // dispose observer for Class re-use. refer to ConnectorImpl.
587 private Observer disposeObserver;
588
589 // ConnectorImpl loaded by a different class loader can not access it.
590 // i.e., runtime package of <ConnectorImpl, L1> is not the same that of
591 // <VirtualMachineImpl, L2> when L1 != L2. So, package private method
592 // can be called reflectively after using setAccessible(true).
593
594 void setDisposeObserver(Observer observer) {
595 disposeObserver = observer;
596 }
597
598 private void notifyDispose() {
599 if (Assert.ASSERTS_ENABLED) {
600 Assert.that(disposeObserver != null, "null VM.dispose observer");
601 }
602 disposeObserver.update(null, null);
603 }
604
605 public void dispose() {
606 saAgent.detach();
607 notifyDispose();
608 }
609
610 public void exit(int exitCode) {
611 throwNotReadOnlyException("VirtualMachine.exit(int)");
612 }
613
614 public boolean canBeModified() {
615 return false;
616 }
617
618 public boolean canWatchFieldModification() {
619 return false;
620 }
621
622 public boolean canWatchFieldAccess() {
623 return false;
624 }
625
626 public boolean canGetBytecodes() {
627 return true;
628 }
629
630 public boolean canGetSyntheticAttribute() {
631 return true;
632 }
633
634 // FIXME: For now, all monitor capabilities are disabled
635 public boolean canGetOwnedMonitorInfo() {
636 return false;
637 }
638
639 public boolean canGetCurrentContendedMonitor() {
640 return false;
641 }
642
643 public boolean canGetMonitorInfo() {
644 return false;
645 }
646
647 // because this SA works only with 1.5 and update releases
648 // this should always succeed unlike JVMDI/JDI.
649 public boolean canGet1_5LanguageFeatures() {
650 return true;
651 }
652
653 public boolean canUseInstanceFilters() {
654 return false;
655 }
656
657 public boolean canRedefineClasses() {
658 return false;
659 }
660
661 public boolean canAddMethod() {
662 return false;
663 }
664
665 public boolean canUnrestrictedlyRedefineClasses() {
666 return false;
667 }
668
669 public boolean canPopFrames() {
670 return false;
671 }
672
673 public boolean canGetSourceDebugExtension() {
674 // We can use InstanceKlass.getSourceDebugExtension only if
675 // ClassFileParser parsed the info. But, ClassFileParser parses
676 // SourceDebugExtension attribute only if corresponding JVMDI/TI
677 // capability is set to true. Currently, vmStructs does not expose
678 // JVMDI/TI capabilities and hence we conservatively assume false.
679 return false;
680 }
681
682 public boolean canRequestVMDeathEvent() {
683 return false;
684 }
685
686 // new method since 1.6
687 public boolean canForceEarlyReturn() {
688 return false;
689 }
690
691 // new method since 1.6
692 public boolean canGetConstantPool() {
693 return true;
694 }
695
696 // new method since 1.6
697 public boolean canGetClassFileVersion() {
698 return true;
699 }
700
701 // new method since 1.6.
702 public boolean canGetMethodReturnValues() {
703 return false;
704 }
705
706 // new method since 1.6
707 // Real body will be supplied later.
708 public boolean canGetInstanceInfo() {
709 return true;
710 }
711
712 // new method since 1.6
713 public boolean canUseSourceNameFilters() {
714 return false;
715 }
716
717 // new method since 1.6.
718 public boolean canRequestMonitorEvents() {
719 return false;
720 }
721
722 // new method since 1.6.
723 public boolean canGetMonitorFrameInfo() {
724 return true;
725 }
726
727 // new method since 1.6
728 // Real body will be supplied later.
729 public long[] instanceCounts(List classes) {
730 if (!canGetInstanceInfo()) {
731 throw new UnsupportedOperationException(
732 "target does not support getting instances");
733 }
734
735 final long[] retValue = new long[classes.size()] ;
736
737 final Klass [] klassArray = new Klass[classes.size()];
738
739 boolean allAbstractClasses = true;
740 for (int i=0; i < classes.size(); i++) {
741 ReferenceTypeImpl rti = (ReferenceTypeImpl)classes.get(i);
742 klassArray[i] = rti.ref();
743 retValue[i]=0;
744 if (!(rti.isAbstract() || ((ReferenceType)rti instanceof InterfaceType))) {
745 allAbstractClasses = false;
746 }
747 }
748
749 if (allAbstractClasses) {
750 return retValue;
751 }
752 final int size = classes.size();
753 saObjectHeap.iterate(new DefaultHeapVisitor() {
754 public boolean doObj(Oop oop) {
755 for (int i=0; i < size; i++) {
756 if (klassArray[i].equals(oop.getKlass())) {
757 retValue[i]++;
758 break;
759 }
760 }
761 return false;
762 }
763 });
764
765 return retValue;
766 }
767
768 private List getPath (String pathName) {
769 String cp = saVM.getSystemProperty(pathName);
770 String pathSep = saVM.getSystemProperty("path.separator");
771 ArrayList al = new ArrayList();
772 StringTokenizer st = new StringTokenizer(cp, pathSep);
773 while (st.hasMoreTokens()) {
774 al.add(st.nextToken());
775 }
776 al.trimToSize();
777 return al;
778 }
779
780 public List classPath() {
781 return getPath("java.class.path");
782 }
783
784 public List bootClassPath() {
785 return getPath("sun.boot.class.path");
786 }
787
788 public String baseDirectory() {
789 return saVM.getSystemProperty("user.dir");
790 }
791
792 public void setDefaultStratum(String stratum) {
793 defaultStratum = stratum;
794 }
795
796 public String getDefaultStratum() {
797 return defaultStratum;
798 }
799
800 public String description() {
801 String[] versionParts = {"" + vmmgr.majorInterfaceVersion(),
802 "" + vmmgr.minorInterfaceVersion(),
803 name()};
804 return java.text.MessageFormat.format(java.util.ResourceBundle.
805 getBundle("com.sun.tools.jdi.resources.jdi").getString("version_format"),
806 versionParts);
807 }
808
809 public String version() {
810 return saVM.getSystemProperty("java.version");
811 }
812
813 public String name() {
814 StringBuffer sb = new StringBuffer();
815 sb.append("JVM version ");
816 sb.append(version());
817 sb.append(" (");
818 sb.append(saVM.getSystemProperty("java.vm.name"));
819 sb.append(", ");
820 sb.append(saVM.getSystemProperty("java.vm.info"));
821 sb.append(")");
822 return sb.toString();
823 }
824
825 // from interface Mirror
826 public VirtualMachine virtualMachine() {
827 return this;
828 }
829
830 public String toString() {
831 return name();
832 }
833
834 public void setDebugTraceMode(int traceFlags) {
835 // spec. says output is implementation dependent
836 // and trace mode may be ignored. we ignore it :-)
837 }
838
839 // heap walking API
840
841 // capability check
842 public boolean canWalkHeap() {
843 return true;
844 }
845
846 // return a list of all objects in heap
847 public List/*<ObjectReference>*/ allObjects() {
848 final List objects = new ArrayList(0);
849 saObjectHeap.iterate(
850 new DefaultHeapVisitor() {
851 public boolean doObj(Oop oop) {
852 objects.add(objectMirror(oop));
853 return false;
854 }
855 });
856 return objects;
857 }
858
859 // equivalent to objectsByType(type, true)
860 public List/*<ObjectReference>*/ objectsByType(ReferenceType type) {
861 return objectsByType(type, true);
862 }
863
864 // returns objects of type exactly equal to given type
865 private List/*<ObjectReference>*/ objectsByExactType(ReferenceType type) {
866 final List objects = new ArrayList(0);
867 final Klass givenKls = ((ReferenceTypeImpl)type).ref();
868 saObjectHeap.iterate(new DefaultHeapVisitor() {
869 public boolean doObj(Oop oop) {
870 if (givenKls.equals(oop.getKlass())) {
871 objects.add(objectMirror(oop));
872 }
873 return false;
874 }
875 });
876 return objects;
877 }
878
879 // returns objects of given type as well as it's subtypes
880 private List/*<ObjectReference>*/ objectsBySubType(ReferenceType type) {
881 final List objects = new ArrayList(0);
882 final ReferenceType givenType = type;
883 saObjectHeap.iterate(new DefaultHeapVisitor() {
884 public boolean doObj(Oop oop) {
885 ReferenceTypeImpl curType = (ReferenceTypeImpl) referenceType(oop.getKlass());
886 if (curType.isAssignableTo(givenType)) {
887 objects.add(objectMirror(oop));
888 }
889 return false;
890 }
891 });
892 return objects;
893 }
894
895 // includeSubtypes - do you want to include subclass/subtype instances of given
896 // ReferenceType or do we want objects of exact type only?
897 public List/*<ObjectReference>*/ objectsByType(ReferenceType type, boolean includeSubtypes) {
898 Klass kls = ((ReferenceTypeImpl)type).ref();
899 if (kls instanceof InstanceKlass) {
900 InstanceKlass ik = (InstanceKlass) kls;
901 if (ik.isInterface()) {
902 if (ik.nofImplementors() == 0L) {
903 return new ArrayList(0);
904 }
905 } else {
906 // if the Klass is final or if there are no subklasses loaded yet
907 if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) {
908 includeSubtypes = false;
909 }
910 }
911 } else {
912 // no subtypes for primitive array types
913 ArrayTypeImpl arrayType = (ArrayTypeImpl) type;
914 try {
915 Type componentType = arrayType.componentType();
916 if (componentType instanceof PrimitiveType) {
917 includeSubtypes = false;
918 }
919 } catch (ClassNotLoadedException cnle) {
920 // ignore. component type not yet loaded
921 }
922 }
923
924 if (includeSubtypes) {
925 return objectsBySubType(type);
926 } else {
927 return objectsByExactType(type);
928 }
929 }
930
931 Type findBootType(String signature) throws ClassNotLoadedException {
932 List types = allClasses();
933 Iterator iter = types.iterator();
934 while (iter.hasNext()) {
935 ReferenceType type = (ReferenceType)iter.next();
936 if ((type.classLoader() == null) &&
937 (type.signature().equals(signature))) {
938 return type;
939 }
940 }
941 JNITypeParser parser = new JNITypeParser(signature);
942 throw new ClassNotLoadedException(parser.typeName(),
943 "Type " + parser.typeName() + " not loaded");
944 }
945
946 BooleanType theBooleanType() {
947 if (theBooleanType == null) {
948 synchronized(this) {
949 if (theBooleanType == null) {
950 theBooleanType = new BooleanTypeImpl(this);
951 }
952 }
953 }
954 return theBooleanType;
955 }
956
957 ByteType theByteType() {
958 if (theByteType == null) {
959 synchronized(this) {
960 if (theByteType == null) {
961 theByteType = new ByteTypeImpl(this);
962 }
963 }
964 }
965 return theByteType;
966 }
967
968 CharType theCharType() {
969 if (theCharType == null) {
970 synchronized(this) {
971 if (theCharType == null) {
972 theCharType = new CharTypeImpl(this);
973 }
974 }
975 }
976 return theCharType;
977 }
978
979 ShortType theShortType() {
980 if (theShortType == null) {
981 synchronized(this) {
982 if (theShortType == null) {
983 theShortType = new ShortTypeImpl(this);
984 }
985 }
986 }
987 return theShortType;
988 }
989
990 IntegerType theIntegerType() {
991 if (theIntegerType == null) {
992 synchronized(this) {
993 if (theIntegerType == null) {
994 theIntegerType = new IntegerTypeImpl(this);
995 }
996 }
997 }
998 return theIntegerType;
999 }
1000
1001 LongType theLongType() {
1002 if (theLongType == null) {
1003 synchronized(this) {
1004 if (theLongType == null) {
1005 theLongType = new LongTypeImpl(this);
1006 }
1007 }
1008 }
1009 return theLongType;
1010 }
1011
1012 FloatType theFloatType() {
1013 if (theFloatType == null) {
1014 synchronized(this) {
1015 if (theFloatType == null) {
1016 theFloatType = new FloatTypeImpl(this);
1017 }
1018 }
1019 }
1020 return theFloatType;
1021 }
1022
1023 DoubleType theDoubleType() {
1024 if (theDoubleType == null) {
1025 synchronized(this) {
1026 if (theDoubleType == null) {
1027 theDoubleType = new DoubleTypeImpl(this);
1028 }
1029 }
1030 }
1031 return theDoubleType;
1032 }
1033
1034 VoidType theVoidType() {
1035 if (theVoidType == null) {
1036 synchronized(this) {
1037 if (theVoidType == null) {
1038 theVoidType = new VoidTypeImpl(this);
1039 }
1040 }
1041 }
1042 return theVoidType;
1043 }
1044
1045 PrimitiveType primitiveTypeMirror(char tag) {
1046 switch (tag) {
1047 case 'Z':
1048 return theBooleanType();
1049 case 'B':
1050 return theByteType();
1051 case 'C':
1052 return theCharType();
1053 case 'S':
1054 return theShortType();
1055 case 'I':
1056 return theIntegerType();
1057 case 'J':
1058 return theLongType();
1059 case 'F':
1060 return theFloatType();
1061 case 'D':
1062 return theDoubleType();
1063 default:
1064 throw new IllegalArgumentException("Unrecognized primitive tag " + tag);
1065 }
1066 }
1067
1068 private void processQueue() {
1069 Reference ref;
1070 while ((ref = referenceQueue.poll()) != null) {
1071 SoftObjectReference softRef = (SoftObjectReference)ref;
1072 removeObjectMirror(softRef);
1073 }
1074 }
1075
1076 // Address value is used as uniqueID by ObjectReferenceImpl
1077 long getAddressValue(Oop obj) {
1078 return vm.saVM.getDebugger().getAddressValue(obj.getHandle());
1079 }
1080
1081 synchronized ObjectReferenceImpl objectMirror(Oop key) {
1082
1083 // Handle any queue elements that are not strongly reachable
1084 processQueue();
1085
1086 if (key == null) {
1087 return null;
1088 }
1089 ObjectReferenceImpl object = null;
1090
1091 /*
1092 * Attempt to retrieve an existing object object reference
1093 */
1094 SoftObjectReference ref = (SoftObjectReference)objectsByID.get(key);
1095 if (ref != null) {
1096 object = ref.object();
1097 }
1098
1099 /*
1100 * If the object wasn't in the table, or it's soft reference was
1101 * cleared, create a new instance.
1102 */
1103 if (object == null) {
1104 if (key instanceof Instance) {
1105 // look for well-known classes
1106 Symbol className = key.getKlass().getName();
1107 if (Assert.ASSERTS_ENABLED) {
1108 Assert.that(className != null, "Null class name");
1109 }
1110 Instance inst = (Instance) key;
1111 if (className.equals(javaLangString)) {
1112 object = new StringReferenceImpl(this, inst);
1113 } else if (className.equals(javaLangThread)) {
1114 object = new ThreadReferenceImpl(this, inst);
1115 } else if (className.equals(javaLangThreadGroup)) {
1116 object = new ThreadGroupReferenceImpl(this, inst);
1117 } else if (className.equals(javaLangClass)) {
1118 object = new ClassObjectReferenceImpl(this, inst);
1119 } else if (className.equals(javaLangClassLoader)) {
1120 object = new ClassLoaderReferenceImpl(this, inst);
1121 } else {
1122 // not a well-known class. But the base class may be
1123 // one of the known classes.
1124 Klass kls = key.getKlass().getSuper();
1125 while (kls != null) {
1126 className = kls.getName();
1127 // java.lang.Class and java.lang.String are final classes
1128 if (className.equals(javaLangThread)) {
1129 object = new ThreadReferenceImpl(this, inst);
1130 break;
1131 } else if(className.equals(javaLangThreadGroup)) {
1132 object = new ThreadGroupReferenceImpl(this, inst);
1133 break;
1134 } else if (className.equals(javaLangClassLoader)) {
1135 object = new ClassLoaderReferenceImpl(this, inst);
1136 break;
1137 }
1138 kls = kls.getSuper();
1139 }
1140
1141 if (object == null) {
1142 // create generic object reference
1143 object = new ObjectReferenceImpl(this, inst);
1144 }
1145 }
1146 } else if (key instanceof TypeArray) {
1147 object = new ArrayReferenceImpl(this, (Array) key);
1148 } else if (key instanceof ObjArray) {
1149 object = new ArrayReferenceImpl(this, (Array) key);
1150 } else {
1151 throw new RuntimeException("unexpected object type " + key);
1152 }
1153 ref = new SoftObjectReference(key, object, referenceQueue);
1154
1155 /*
1156 * If there was no previous entry in the table, we add one here
1157 * If the previous entry was cleared, we replace it here.
1158 */
1159 objectsByID.put(key, ref);
1160 } else {
1161 ref.incrementCount();
1162 }
1163
1164 return object;
1165 }
1166
1167 synchronized void removeObjectMirror(SoftObjectReference ref) {
1168 /*
1169 * This will remove the soft reference if it has not been
1170 * replaced in the cache.
1171 */
1172 objectsByID.remove(ref.key());
1173 }
1174
1175 StringReferenceImpl stringMirror(Instance id) {
1176 return (StringReferenceImpl) objectMirror(id);
1177 }
1178
1179 ArrayReferenceImpl arrayMirror(Array id) {
1180 return (ArrayReferenceImpl) objectMirror(id);
1181 }
1182
1183 ThreadReferenceImpl threadMirror(Instance id) {
1184 return (ThreadReferenceImpl) objectMirror(id);
1185 }
1186
1187 ThreadReferenceImpl threadMirror(JavaThread jt) {
1188 return (ThreadReferenceImpl) objectMirror(jt.getThreadObj());
1189 }
1190
1191 ThreadGroupReferenceImpl threadGroupMirror(Instance id) {
1192 return (ThreadGroupReferenceImpl) objectMirror(id);
1193 }
1194
1195 ClassLoaderReferenceImpl classLoaderMirror(Instance id) {
1196 return (ClassLoaderReferenceImpl) objectMirror(id);
1197 }
1198
1199 ClassObjectReferenceImpl classObjectMirror(Instance id) {
1200 return (ClassObjectReferenceImpl) objectMirror(id);
1201 }
1202
1203 // Use of soft refs and caching stuff here has to be re-examined.
1204 // It might not make sense for JDI - SA.
1205 static private class SoftObjectReference extends SoftReference {
1206 int count;
1207 Object key;
1208
1209 SoftObjectReference(Object key, ObjectReferenceImpl mirror,
1210 ReferenceQueue queue) {
1211 super(mirror, queue);
1212 this.count = 1;
1213 this.key = key;
1214 }
1215
1216 int count() {
1217 return count;
1218 }
1219
1220 void incrementCount() {
1221 count++;
1222 }
1223
1224 Object key() {
1225 return key;
1226 }
1227
1228 ObjectReferenceImpl object() {
1229 return (ObjectReferenceImpl)get();
1230 }
1231 }
1232 }