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 }