1 /* 2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * 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 Windows process debugger 268 // to windbg debugger. SA expects special properties to be set 269 // to choose other debuggers. We will set those here before 270 // attaching to SA agent. 271 272 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); 273 } 274 275 // we reflectively use newly spec'ed class because our ALT_BOOTDIR 276 // is 1.4.2 and not 1.5. 277 private static Class vmCannotBeModifiedExceptionClass = null; 278 void throwNotReadOnlyException(String operation) { 279 RuntimeException re = null; 280 if (vmCannotBeModifiedExceptionClass == null) { 281 try { 282 vmCannotBeModifiedExceptionClass = Class.forName("com.sun.jdi.VMCannotBeModifiedException"); 283 } catch (ClassNotFoundException cnfe) { 284 vmCannotBeModifiedExceptionClass = UnsupportedOperationException.class; 285 } 286 } 287 try { 288 re = (RuntimeException) vmCannotBeModifiedExceptionClass.newInstance(); 289 } catch (Exception exp) { 290 re = new RuntimeException(exp.getMessage()); 291 } 292 throw re; 293 } 294 295 public boolean equals(Object obj) { 296 // Oh boy; big recursion troubles if we don't have this! 297 // See MirrorImpl.equals 298 return this == obj; 299 } 300 301 public int hashCode() { 302 // big recursion if we don't have this. See MirrorImpl.hashCode 303 return System.identityHashCode(this); 304 } 305 306 public List classesByName(String className) { 307 String signature = JNITypeParser.typeNameToSignature(className); 308 List list; 309 if (!retrievedAllTypes) { 310 retrieveAllClasses(); 311 } 312 list = findReferenceTypes(signature); 313 return Collections.unmodifiableList(list); 314 } 315 316 public List allClasses() { 317 if (!retrievedAllTypes) { 318 retrieveAllClasses(); 319 } 320 ArrayList a; 321 synchronized (this) { 322 a = new ArrayList(typesBySignature); 323 } 324 return Collections.unmodifiableList(a); 325 } 326 327 // classes loaded by bootstrap loader 328 List bootstrapClasses() { 329 if (bootstrapClasses == null) { 330 bootstrapClasses = new ArrayList(); 331 List all = allClasses(); 332 for (Iterator itr = all.iterator(); itr.hasNext();) { 333 ReferenceType type = (ReferenceType) itr.next(); 334 if (type.classLoader() == null) { 335 bootstrapClasses.add(type); 336 } 337 } 338 } 339 return bootstrapClasses; 340 } 341 342 private synchronized List findReferenceTypes(String signature) { 343 if (typesByID == null) { 344 return new ArrayList(0); 345 } 346 347 // we haven't sorted types by signatures. But we can take 348 // advantage of comparing symbols instead of name. In the worst 349 // case, we will be comparing N addresses rather than N strings 350 // where N being total no. of classes in allClasses() list. 351 352 // The signature could be Lx/y/z; or [.... 353 // If it is Lx/y/z; the internal type name is x/y/x 354 // for array klasses internal type name is same as 355 // signature 356 String typeName = null; 357 if (signature.charAt(0) == 'L') { 358 typeName = signature.substring(1, signature.length() - 1); 359 } else { 360 typeName = signature; 361 } 362 363 Symbol typeNameSym = saSymbolTable().probe(typeName); 364 // if there is no symbol in VM, then we wouldn't have that type 365 if (typeNameSym == null) { 366 return new ArrayList(0); 367 } 368 369 Iterator iter = typesBySignature.iterator(); 370 List list = new ArrayList(); 371 while (iter.hasNext()) { 372 // We have cached type name as symbol in reference type 373 ReferenceTypeImpl type = (ReferenceTypeImpl)iter.next(); 374 if (typeNameSym.equals(type.typeNameAsSymbol())) { 375 list.add(type); 376 } 377 } 378 return list; 379 } 380 381 private void retrieveAllClasses() { 382 final List saKlasses = new ArrayList(); 383 SystemDictionary.ClassVisitor visitor = new SystemDictionary.ClassVisitor() { 384 public void visit(Klass k) { 385 for (Klass l = k; l != null; l = l.arrayKlassOrNull()) { 386 // for non-array classes filter out un-prepared classes 387 // refer to 'allClasses' in share/back/VirtualMachineImpl.c 388 if (l instanceof ArrayKlass) { 389 saKlasses.add(l); 390 } else { 391 int status = l.getClassStatus(); 392 if ((status & JVMDIClassStatus.PREPARED) != 0) { 393 saKlasses.add(l); 394 } 395 } 396 } 397 } 398 }; 399 400 // refer to jvmtiGetLoadedClasses.cpp - getLoadedClasses in VM code. 401 402 // classes from SystemDictionary 403 saSystemDictionary.classesDo(visitor); 404 405 // From SystemDictionary we do not get primitive single 406 // dimensional array classes. add primitive single dimensional array 407 // klasses from Universe. 408 saVM.getUniverse().basicTypeClassesDo(visitor); 409 410 // Hold lock during processing to improve performance 411 // and to have safe check/set of retrievedAllTypes 412 synchronized (this) { 413 if (!retrievedAllTypes) { 414 // Number of classes 415 int count = saKlasses.size(); 416 for (int ii = 0; ii < count; ii++) { 417 Klass kk = (Klass)saKlasses.get(ii); 418 ReferenceTypeImpl type = referenceType(kk); 419 } 420 retrievedAllTypes = true; 421 } 422 } 423 } 424 425 ReferenceTypeImpl referenceType(Klass kk) { 426 ReferenceTypeImpl retType = null; 427 synchronized (this) { 428 if (typesByID != null) { 429 retType = (ReferenceTypeImpl)typesByID.get(kk); 430 } 431 if (retType == null) { 432 retType = addReferenceType(kk); 433 } 434 } 435 return retType; 436 } 437 438 private void initReferenceTypes() { 439 typesByID = new HashMap(); 440 typesBySignature = new ArrayList(); 441 } 442 443 private synchronized ReferenceTypeImpl addReferenceType(Klass kk) { 444 if (typesByID == null) { 445 initReferenceTypes(); 446 } 447 ReferenceTypeImpl newRefType = null; 448 if (kk instanceof ObjArrayKlass || kk instanceof TypeArrayKlass) { 449 newRefType = new ArrayTypeImpl(this, (ArrayKlass)kk); 450 } else if (kk instanceof InstanceKlass) { 451 if (kk.isInterface()) { 452 newRefType = new InterfaceTypeImpl(this, (InstanceKlass)kk); 453 } else { 454 newRefType = new ClassTypeImpl(this, (InstanceKlass)kk); 455 } 456 } else { 457 throw new RuntimeException("should not reach here:" + kk); 458 } 459 460 typesByID.put(kk, newRefType); 461 typesBySignature.add(newRefType); 462 return newRefType; 463 } 464 465 ThreadGroup threadGroupForJDI() { 466 return threadGroupForJDI; 467 } 468 469 public void redefineClasses(Map classToBytes) { 470 throwNotReadOnlyException("VirtualMachineImpl.redefineClasses()"); 471 } 472 473 private List getAllThreads() { 474 if (allThreads == null) { 475 allThreads = new ArrayList(10); // Might be enough, might not be 476 for (sun.jvm.hotspot.runtime.JavaThread thread = 477 saVM.getThreads().first(); thread != null; 478 thread = thread.next()) { 479 // refer to JvmtiEnv::GetAllThreads in jvmtiEnv.cpp. 480 // filter out the hidden-from-external-view threads. 481 if (thread.isHiddenFromExternalView() == false) { 482 ThreadReferenceImpl myThread = threadMirror(thread); 483 allThreads.add(myThread); 484 } 485 } 486 } 487 return allThreads; 488 } 489 490 public List allThreads() { //fixme jjh 491 return Collections.unmodifiableList(getAllThreads()); 492 } 493 494 public void suspend() { 495 throwNotReadOnlyException("VirtualMachineImpl.suspend()"); 496 } 497 498 public void resume() { 499 throwNotReadOnlyException("VirtualMachineImpl.resume()"); 500 } 501 502 public List topLevelThreadGroups() { //fixme jjh 503 // The doc for ThreadGroup says that The top-level thread group 504 // is the only thread group whose parent is null. This means there is 505 // only one top level thread group. There will be a thread in this 506 // group so we will just find a thread whose threadgroup has no parent 507 // and that will be it. 508 509 if (topLevelGroups == null) { 510 topLevelGroups = new ArrayList(1); 511 Iterator myIt = getAllThreads().iterator(); 512 while (myIt.hasNext()) { 513 ThreadReferenceImpl myThread = (ThreadReferenceImpl)myIt.next(); 514 ThreadGroupReference myGroup = myThread.threadGroup(); 515 ThreadGroupReference myParent = myGroup.parent(); 516 if (myGroup.parent() == null) { 517 topLevelGroups.add(myGroup); 518 break; 519 } 520 } 521 } 522 return Collections.unmodifiableList(topLevelGroups); 523 } 524 525 public EventQueue eventQueue() { 526 throwNotReadOnlyException("VirtualMachine.eventQueue()"); 527 return null; 528 } 529 530 public EventRequestManager eventRequestManager() { 531 throwNotReadOnlyException("VirtualMachineImpl.eventRequestManager()"); 532 return null; 533 } 534 535 public BooleanValue mirrorOf(boolean value) { 536 return new BooleanValueImpl(this,value); 537 } 538 539 public ByteValue mirrorOf(byte value) { 540 return new ByteValueImpl(this,value); 541 } 542 543 public CharValue mirrorOf(char value) { 544 return new CharValueImpl(this,value); 545 } 546 547 public ShortValue mirrorOf(short value) { 548 return new ShortValueImpl(this,value); 549 } 550 551 public IntegerValue mirrorOf(int value) { 552 return new IntegerValueImpl(this,value); 553 } 554 555 public LongValue mirrorOf(long value) { 556 return new LongValueImpl(this,value); 557 } 558 559 public FloatValue mirrorOf(float value) { 560 return new FloatValueImpl(this,value); 561 } 562 563 public DoubleValue mirrorOf(double value) { 564 return new DoubleValueImpl(this,value); 565 } 566 567 public StringReference mirrorOf(String value) { 568 throwNotReadOnlyException("VirtualMachinestop.mirrorOf(String)"); 569 return null; 570 } 571 572 public VoidValue mirrorOfVoid() { 573 if (voidVal == null) { 574 voidVal = new VoidValueImpl(this); 575 } 576 return voidVal; 577 } 578 579 580 public Process process() { 581 throwNotReadOnlyException("VirtualMachine.process"); 582 return null; 583 } 584 585 // dispose observer for Class re-use. refer to ConnectorImpl. 586 private Observer disposeObserver; 587 588 // ConnectorImpl loaded by a different class loader can not access it. 589 // i.e., runtime package of <ConnectorImpl, L1> is not the same that of 590 // <VirtualMachineImpl, L2> when L1 != L2. So, package private method 591 // can be called reflectively after using setAccessible(true). 592 593 void setDisposeObserver(Observer observer) { 594 disposeObserver = observer; 595 } 596 597 private void notifyDispose() { 598 if (Assert.ASSERTS_ENABLED) { 599 Assert.that(disposeObserver != null, "null VM.dispose observer"); 600 } 601 disposeObserver.update(null, null); 602 } 603 604 public void dispose() { 605 saAgent.detach(); 606 notifyDispose(); 607 } 608 609 public void exit(int exitCode) { 610 throwNotReadOnlyException("VirtualMachine.exit(int)"); 611 } 612 613 public boolean canBeModified() { 614 return false; 615 } 616 617 public boolean canWatchFieldModification() { 618 return false; 619 } 620 621 public boolean canWatchFieldAccess() { 622 return false; 623 } 624 625 public boolean canGetBytecodes() { 626 return true; 627 } 628 629 public boolean canGetSyntheticAttribute() { 630 return true; 631 } 632 633 // FIXME: For now, all monitor capabilities are disabled 634 public boolean canGetOwnedMonitorInfo() { 635 return false; 636 } 637 638 public boolean canGetCurrentContendedMonitor() { 639 return false; 640 } 641 642 public boolean canGetMonitorInfo() { 643 return false; 644 } 645 646 // because this SA works only with 1.5 and update releases 647 // this should always succeed unlike JVMDI/JDI. 648 public boolean canGet1_5LanguageFeatures() { 649 return true; 650 } 651 652 public boolean canUseInstanceFilters() { 653 return false; 654 } 655 656 public boolean canRedefineClasses() { 657 return false; 658 } 659 660 public boolean canAddMethod() { 661 return false; 662 } 663 664 public boolean canUnrestrictedlyRedefineClasses() { 665 return false; 666 } 667 668 public boolean canPopFrames() { 669 return false; 670 } 671 672 public boolean canGetSourceDebugExtension() { 673 // We can use InstanceKlass.getSourceDebugExtension only if 674 // ClassFileParser parsed the info. But, ClassFileParser parses 675 // SourceDebugExtension attribute only if corresponding JVMDI/TI 676 // capability is set to true. Currently, vmStructs does not expose 677 // JVMDI/TI capabilities and hence we conservatively assume false. 678 return false; 679 } 680 681 public boolean canRequestVMDeathEvent() { 682 return false; 683 } 684 685 // new method since 1.6 686 public boolean canForceEarlyReturn() { 687 return false; 688 } 689 690 // new method since 1.6 691 public boolean canGetConstantPool() { 692 return true; 693 } 694 695 // new method since 1.6 696 public boolean canGetClassFileVersion() { 697 return true; 698 } 699 700 // new method since 1.6. 701 public boolean canGetMethodReturnValues() { 702 return false; 703 } 704 705 // new method since 1.6 706 // Real body will be supplied later. 707 public boolean canGetInstanceInfo() { 708 return true; 709 } 710 711 // new method since 1.6 712 public boolean canUseSourceNameFilters() { 713 return false; 714 } 715 716 // new method since 1.6. 717 public boolean canRequestMonitorEvents() { 718 return false; 719 } 720 721 // new method since 1.6. 722 public boolean canGetMonitorFrameInfo() { 723 return true; 724 } 725 726 // new method since 1.6 727 // Real body will be supplied later. 728 public long[] instanceCounts(List classes) { 729 if (!canGetInstanceInfo()) { 730 throw new UnsupportedOperationException( 731 "target does not support getting instances"); 732 } 733 734 final long[] retValue = new long[classes.size()] ; 735 736 final Klass [] klassArray = new Klass[classes.size()]; 737 738 boolean allAbstractClasses = true; 739 for (int i=0; i < classes.size(); i++) { 740 ReferenceTypeImpl rti = (ReferenceTypeImpl)classes.get(i); 741 klassArray[i] = rti.ref(); 742 retValue[i]=0; 743 if (!(rti.isAbstract() || ((ReferenceType)rti instanceof InterfaceType))) { 744 allAbstractClasses = false; 745 } 746 } 747 748 if (allAbstractClasses) { 749 return retValue; 750 } 751 final int size = classes.size(); 752 saObjectHeap.iterate(new DefaultHeapVisitor() { 753 public boolean doObj(Oop oop) { 754 for (int i=0; i < size; i++) { 755 if (klassArray[i].equals(oop.getKlass())) { 756 retValue[i]++; 757 break; 758 } 759 } 760 return false; 761 } 762 }); 763 764 return retValue; 765 } 766 767 private List getPath (String pathName) { 768 String cp = saVM.getSystemProperty(pathName); 769 String pathSep = saVM.getSystemProperty("path.separator"); 770 ArrayList al = new ArrayList(); 771 StringTokenizer st = new StringTokenizer(cp, pathSep); 772 while (st.hasMoreTokens()) { 773 al.add(st.nextToken()); 774 } 775 al.trimToSize(); 776 return al; 777 } 778 779 public List classPath() { 780 return getPath("java.class.path"); 781 } 782 783 public List<String> bootClassPath() { 784 return Collections.emptyList(); 785 } 786 787 public String baseDirectory() { 788 return saVM.getSystemProperty("user.dir"); 789 } 790 791 public void setDefaultStratum(String stratum) { 792 defaultStratum = stratum; 793 } 794 795 public String getDefaultStratum() { 796 return defaultStratum; 797 } 798 799 public String description() { 800 return java.text.MessageFormat.format(java.util.ResourceBundle. 801 getBundle("com.sun.tools.jdi.resources.jdi").getString("version_format"), 802 "" + vmmgr.majorInterfaceVersion(), 803 "" + vmmgr.minorInterfaceVersion(), 804 name()); 805 } 806 807 public String version() { 808 return saVM.getSystemProperty("java.version"); 809 } 810 811 public String name() { 812 StringBuffer sb = new StringBuffer(); 813 sb.append("JVM version "); 814 sb.append(version()); 815 sb.append(" ("); 816 sb.append(saVM.getSystemProperty("java.vm.name")); 817 sb.append(", "); 818 sb.append(saVM.getSystemProperty("java.vm.info")); 819 sb.append(")"); 820 return sb.toString(); 821 } 822 823 // from interface Mirror 824 public VirtualMachine virtualMachine() { 825 return this; 826 } 827 828 public String toString() { 829 return name(); 830 } 831 832 public void setDebugTraceMode(int traceFlags) { 833 // spec. says output is implementation dependent 834 // and trace mode may be ignored. we ignore it :-) 835 } 836 837 // heap walking API 838 839 // capability check 840 public boolean canWalkHeap() { 841 return true; 842 } 843 844 // return a list of all objects in heap 845 public List/*<ObjectReference>*/ allObjects() { 846 final List objects = new ArrayList(0); 847 saObjectHeap.iterate( 848 new DefaultHeapVisitor() { 849 public boolean doObj(Oop oop) { 850 objects.add(objectMirror(oop)); 851 return false; 852 } 853 }); 854 return objects; 855 } 856 857 // equivalent to objectsByType(type, true) 858 public List/*<ObjectReference>*/ objectsByType(ReferenceType type) { 859 return objectsByType(type, true); 860 } 861 862 // returns objects of type exactly equal to given type 863 private List/*<ObjectReference>*/ objectsByExactType(ReferenceType type) { 864 final List objects = new ArrayList(0); 865 final Klass givenKls = ((ReferenceTypeImpl)type).ref(); 866 saObjectHeap.iterate(new DefaultHeapVisitor() { 867 public boolean doObj(Oop oop) { 868 if (givenKls.equals(oop.getKlass())) { 869 objects.add(objectMirror(oop)); 870 } 871 return false; 872 } 873 }); 874 return objects; 875 } 876 877 // returns objects of given type as well as it's subtypes 878 private List/*<ObjectReference>*/ objectsBySubType(ReferenceType type) { 879 final List objects = new ArrayList(0); 880 final ReferenceType givenType = type; 881 saObjectHeap.iterate(new DefaultHeapVisitor() { 882 public boolean doObj(Oop oop) { 883 ReferenceTypeImpl curType = (ReferenceTypeImpl) referenceType(oop.getKlass()); 884 if (curType.isAssignableTo(givenType)) { 885 objects.add(objectMirror(oop)); 886 } 887 return false; 888 } 889 }); 890 return objects; 891 } 892 893 // includeSubtypes - do you want to include subclass/subtype instances of given 894 // ReferenceType or do we want objects of exact type only? 895 public List/*<ObjectReference>*/ objectsByType(ReferenceType type, boolean includeSubtypes) { 896 Klass kls = ((ReferenceTypeImpl)type).ref(); 897 if (kls instanceof InstanceKlass) { 898 InstanceKlass ik = (InstanceKlass) kls; 899 // if the Klass is final or if there are no subklasses loaded yet 900 if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) { 901 includeSubtypes = false; 902 } 903 } else { 904 // no subtypes for primitive array types 905 ArrayTypeImpl arrayType = (ArrayTypeImpl) type; 906 try { 907 Type componentType = arrayType.componentType(); 908 if (componentType instanceof PrimitiveType) { 909 includeSubtypes = false; 910 } 911 } catch (ClassNotLoadedException cnle) { 912 // ignore. component type not yet loaded 913 } 914 } 915 916 if (includeSubtypes) { 917 return objectsBySubType(type); 918 } else { 919 return objectsByExactType(type); 920 } 921 } 922 923 Type findBootType(String signature) throws ClassNotLoadedException { 924 List types = allClasses(); 925 Iterator iter = types.iterator(); 926 while (iter.hasNext()) { 927 ReferenceType type = (ReferenceType)iter.next(); 928 if ((type.classLoader() == null) && 929 (type.signature().equals(signature))) { 930 return type; 931 } 932 } 933 JNITypeParser parser = new JNITypeParser(signature); 934 throw new ClassNotLoadedException(parser.typeName(), 935 "Type " + parser.typeName() + " not loaded"); 936 } 937 938 BooleanType theBooleanType() { 939 if (theBooleanType == null) { 940 synchronized(this) { 941 if (theBooleanType == null) { 942 theBooleanType = new BooleanTypeImpl(this); 943 } 944 } 945 } 946 return theBooleanType; 947 } 948 949 ByteType theByteType() { 950 if (theByteType == null) { 951 synchronized(this) { 952 if (theByteType == null) { 953 theByteType = new ByteTypeImpl(this); 954 } 955 } 956 } 957 return theByteType; 958 } 959 960 CharType theCharType() { 961 if (theCharType == null) { 962 synchronized(this) { 963 if (theCharType == null) { 964 theCharType = new CharTypeImpl(this); 965 } 966 } 967 } 968 return theCharType; 969 } 970 971 ShortType theShortType() { 972 if (theShortType == null) { 973 synchronized(this) { 974 if (theShortType == null) { 975 theShortType = new ShortTypeImpl(this); 976 } 977 } 978 } 979 return theShortType; 980 } 981 982 IntegerType theIntegerType() { 983 if (theIntegerType == null) { 984 synchronized(this) { 985 if (theIntegerType == null) { 986 theIntegerType = new IntegerTypeImpl(this); 987 } 988 } 989 } 990 return theIntegerType; 991 } 992 993 LongType theLongType() { 994 if (theLongType == null) { 995 synchronized(this) { 996 if (theLongType == null) { 997 theLongType = new LongTypeImpl(this); 998 } 999 } 1000 } 1001 return theLongType; 1002 } 1003 1004 FloatType theFloatType() { 1005 if (theFloatType == null) { 1006 synchronized(this) { 1007 if (theFloatType == null) { 1008 theFloatType = new FloatTypeImpl(this); 1009 } 1010 } 1011 } 1012 return theFloatType; 1013 } 1014 1015 DoubleType theDoubleType() { 1016 if (theDoubleType == null) { 1017 synchronized(this) { 1018 if (theDoubleType == null) { 1019 theDoubleType = new DoubleTypeImpl(this); 1020 } 1021 } 1022 } 1023 return theDoubleType; 1024 } 1025 1026 VoidType theVoidType() { 1027 if (theVoidType == null) { 1028 synchronized(this) { 1029 if (theVoidType == null) { 1030 theVoidType = new VoidTypeImpl(this); 1031 } 1032 } 1033 } 1034 return theVoidType; 1035 } 1036 1037 PrimitiveType primitiveTypeMirror(char tag) { 1038 switch (tag) { 1039 case 'Z': 1040 return theBooleanType(); 1041 case 'B': 1042 return theByteType(); 1043 case 'C': 1044 return theCharType(); 1045 case 'S': 1046 return theShortType(); 1047 case 'I': 1048 return theIntegerType(); 1049 case 'J': 1050 return theLongType(); 1051 case 'F': 1052 return theFloatType(); 1053 case 'D': 1054 return theDoubleType(); 1055 default: 1056 throw new IllegalArgumentException("Unrecognized primitive tag " + tag); 1057 } 1058 } 1059 1060 private void processQueue() { 1061 Reference ref; 1062 while ((ref = referenceQueue.poll()) != null) { 1063 SoftObjectReference softRef = (SoftObjectReference)ref; 1064 removeObjectMirror(softRef); 1065 } 1066 } 1067 1068 // Address value is used as uniqueID by ObjectReferenceImpl 1069 long getAddressValue(Oop obj) { 1070 return vm.saVM.getDebugger().getAddressValue(obj.getHandle()); 1071 } 1072 1073 synchronized ObjectReferenceImpl objectMirror(Oop key) { 1074 1075 // Handle any queue elements that are not strongly reachable 1076 processQueue(); 1077 1078 if (key == null) { 1079 return null; 1080 } 1081 ObjectReferenceImpl object = null; 1082 1083 /* 1084 * Attempt to retrieve an existing object object reference 1085 */ 1086 SoftObjectReference ref = (SoftObjectReference)objectsByID.get(key); 1087 if (ref != null) { 1088 object = ref.object(); 1089 } 1090 1091 /* 1092 * If the object wasn't in the table, or it's soft reference was 1093 * cleared, create a new instance. 1094 */ 1095 if (object == null) { 1096 if (key instanceof Instance) { 1097 // look for well-known classes 1098 Symbol className = key.getKlass().getName(); 1099 if (Assert.ASSERTS_ENABLED) { 1100 Assert.that(className != null, "Null class name"); 1101 } 1102 Instance inst = (Instance) key; 1103 if (className.equals(javaLangString)) { 1104 object = new StringReferenceImpl(this, inst); 1105 } else if (className.equals(javaLangThread)) { 1106 object = new ThreadReferenceImpl(this, inst); 1107 } else if (className.equals(javaLangThreadGroup)) { 1108 object = new ThreadGroupReferenceImpl(this, inst); 1109 } else if (className.equals(javaLangClass)) { 1110 object = new ClassObjectReferenceImpl(this, inst); 1111 } else if (className.equals(javaLangClassLoader)) { 1112 object = new ClassLoaderReferenceImpl(this, inst); 1113 } else { 1114 // not a well-known class. But the base class may be 1115 // one of the known classes. 1116 Klass kls = key.getKlass().getSuper(); 1117 while (kls != null) { 1118 className = kls.getName(); 1119 // java.lang.Class and java.lang.String are final classes 1120 if (className.equals(javaLangThread)) { 1121 object = new ThreadReferenceImpl(this, inst); 1122 break; 1123 } else if(className.equals(javaLangThreadGroup)) { 1124 object = new ThreadGroupReferenceImpl(this, inst); 1125 break; 1126 } else if (className.equals(javaLangClassLoader)) { 1127 object = new ClassLoaderReferenceImpl(this, inst); 1128 break; 1129 } 1130 kls = kls.getSuper(); 1131 } 1132 1133 if (object == null) { 1134 // create generic object reference 1135 object = new ObjectReferenceImpl(this, inst); 1136 } 1137 } 1138 } else if (key instanceof TypeArray) { 1139 object = new ArrayReferenceImpl(this, (Array) key); 1140 } else if (key instanceof ObjArray) { 1141 object = new ArrayReferenceImpl(this, (Array) key); 1142 } else { 1143 throw new RuntimeException("unexpected object type " + key); 1144 } 1145 ref = new SoftObjectReference(key, object, referenceQueue); 1146 1147 /* 1148 * If there was no previous entry in the table, we add one here 1149 * If the previous entry was cleared, we replace it here. 1150 */ 1151 objectsByID.put(key, ref); 1152 } else { 1153 ref.incrementCount(); 1154 } 1155 1156 return object; 1157 } 1158 1159 synchronized void removeObjectMirror(SoftObjectReference ref) { 1160 /* 1161 * This will remove the soft reference if it has not been 1162 * replaced in the cache. 1163 */ 1164 objectsByID.remove(ref.key()); 1165 } 1166 1167 StringReferenceImpl stringMirror(Instance id) { 1168 return (StringReferenceImpl) objectMirror(id); 1169 } 1170 1171 ArrayReferenceImpl arrayMirror(Array id) { 1172 return (ArrayReferenceImpl) objectMirror(id); 1173 } 1174 1175 ThreadReferenceImpl threadMirror(Instance id) { 1176 return (ThreadReferenceImpl) objectMirror(id); 1177 } 1178 1179 ThreadReferenceImpl threadMirror(JavaThread jt) { 1180 return (ThreadReferenceImpl) objectMirror(jt.getThreadObj()); 1181 } 1182 1183 ThreadGroupReferenceImpl threadGroupMirror(Instance id) { 1184 return (ThreadGroupReferenceImpl) objectMirror(id); 1185 } 1186 1187 ClassLoaderReferenceImpl classLoaderMirror(Instance id) { 1188 return (ClassLoaderReferenceImpl) objectMirror(id); 1189 } 1190 1191 ClassObjectReferenceImpl classObjectMirror(Instance id) { 1192 return (ClassObjectReferenceImpl) objectMirror(id); 1193 } 1194 1195 // Use of soft refs and caching stuff here has to be re-examined. 1196 // It might not make sense for JDI - SA. 1197 static private class SoftObjectReference extends SoftReference { 1198 int count; 1199 Object key; 1200 1201 SoftObjectReference(Object key, ObjectReferenceImpl mirror, 1202 ReferenceQueue queue) { 1203 super(mirror, queue); 1204 this.count = 1; 1205 this.key = key; 1206 } 1207 1208 int count() { 1209 return count; 1210 } 1211 1212 void incrementCount() { 1213 count++; 1214 } 1215 1216 Object key() { 1217 return key; 1218 } 1219 1220 ObjectReferenceImpl object() { 1221 return (ObjectReferenceImpl)get(); 1222 } 1223 } 1224 }