1 /* 2 * Copyright 2000-2009 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.runtime; 26 27 import java.io.*; 28 import java.net.*; 29 import java.util.*; 30 import java.util.regex.*; 31 import sun.jvm.hotspot.code.*; 32 import sun.jvm.hotspot.c1.*; 33 import sun.jvm.hotspot.debugger.*; 34 import sun.jvm.hotspot.interpreter.*; 35 import sun.jvm.hotspot.memory.*; 36 import sun.jvm.hotspot.oops.*; 37 import sun.jvm.hotspot.types.*; 38 import sun.jvm.hotspot.utilities.*; 39 import sun.jvm.hotspot.runtime.*; 40 41 /** <P> This class encapsulates the global state of the VM; the 42 universe, object heap, interpreter, etc. It is a Singleton and 43 must be initialized with a call to initialize() before calling 44 getVM(). </P> 45 46 <P> Many auxiliary classes (i.e., most of the VMObjects) keep 47 needed field offsets in the form of static Field objects. In a 48 debugging system, the VM might be shutdown and re-initialized (on 49 a differently-configured build, i.e., 32- vs. 64-bit), and all old 50 cached state (including fields and field offsets) must be 51 flushed. </P> 52 53 <P> An Observer pattern is used to implement the initialization of 54 such classes. Each such class, in its static initializer, 55 registers an Observer with the VM class via 56 VM.registerVMInitializedObserver(). This Observer is guaranteed to 57 be notified whenever the VM is initialized (or re-initialized). To 58 implement the first-time initialization, the observer is also 59 notified when it registers itself with the VM. (For bootstrapping 60 reasons, this implies that the constructor of VM can not 61 instantiate any such objects, since VM.soleInstance will not have 62 been set yet. This is a bootstrapping issue which may have to be 63 revisited later.) </P> 64 */ 65 66 public class VM { 67 private static VM soleInstance; 68 private static List vmInitializedObservers = new ArrayList(); 69 private List vmResumedObservers = new ArrayList(); 70 private List vmSuspendedObservers = new ArrayList(); 71 private TypeDataBase db; 72 private boolean isBigEndian; 73 /** This is only present if in a debugging system */ 74 private JVMDebugger debugger; 75 private long stackBias; 76 private long logAddressSize; 77 private Universe universe; 78 private ObjectHeap heap; 79 private SymbolTable symbols; 80 private StringTable strings; 81 private SystemDictionary dict; 82 private Threads threads; 83 private ObjectSynchronizer synchronizer; 84 private JNIHandles handles; 85 private Interpreter interpreter; 86 private StubRoutines stubRoutines; 87 private Bytes bytes; 88 /** Flags indicating whether we are attached to a core, C1, or C2 build */ 89 private boolean usingClientCompiler; 90 private boolean usingServerCompiler; 91 /** Flag indicating whether UseTLAB is turned on */ 92 private boolean useTLAB; 93 /** alignment constants */ 94 private boolean isLP64; 95 private int bytesPerLong; 96 private int minObjAlignmentInBytes; 97 private int logMinObjAlignmentInBytes; 98 private int heapWordSize; 99 private int heapOopSize; 100 private int oopSize; 101 /** This is only present in a non-core build */ 102 private CodeCache codeCache; 103 /** This is only present in a C1 build */ 104 private Runtime1 runtime1; 105 /** These constants come from globalDefinitions.hpp */ 106 private int invocationEntryBCI; 107 private int invalidOSREntryBCI; 108 private ReversePtrs revPtrs; 109 private VMRegImpl vmregImpl; 110 111 // System.getProperties from debuggee VM 112 private Properties sysProps; 113 114 // VM version strings come from Abstract_VM_Version class 115 private String vmRelease; 116 private String vmInternalInfo; 117 118 private Flag[] commandLineFlags; 119 private Map flagsMap; 120 121 private static Type intxType; 122 private static Type uintxType; 123 private static CIntegerType boolType; 124 private Boolean sharingEnabled; 125 private Boolean compressedOopsEnabled; 126 127 // command line flags supplied to VM - see struct Flag in globals.hpp 128 public static final class Flag { 129 private String type; 130 private String name; 131 private Address addr; 132 private String kind; 133 134 private Flag(String type, String name, Address addr, String kind) { 135 this.type = type; 136 this.name = name; 137 this.addr = addr; 138 this.kind = kind; 139 } 140 141 public String getType() { 142 return type; 143 } 144 145 public String getName() { 146 return name; 147 } 148 149 public Address getAddress() { 150 return addr; 151 } 152 153 public String getKind() { 154 return kind; 155 } 156 157 public boolean isBool() { 158 return type.equals("bool"); 159 } 160 161 public boolean getBool() { 162 if (Assert.ASSERTS_ENABLED) { 163 Assert.that(isBool(), "not a bool flag!"); 164 } 165 return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned()) 166 != 0; 167 } 168 169 public boolean isIntx() { 170 return type.equals("intx"); 171 } 172 173 public long getIntx() { 174 if (Assert.ASSERTS_ENABLED) { 175 Assert.that(isIntx(), "not a intx flag!"); 176 } 177 return addr.getCIntegerAt(0, intxType.getSize(), false); 178 } 179 180 public boolean isUIntx() { 181 return type.equals("uintx"); 182 } 183 184 public long getUIntx() { 185 if (Assert.ASSERTS_ENABLED) { 186 Assert.that(isUIntx(), "not a uintx flag!"); 187 } 188 return addr.getCIntegerAt(0, uintxType.getSize(), true); 189 } 190 191 public String getValue() { 192 if (isBool()) { 193 return new Boolean(getBool()).toString(); 194 } else if (isIntx()) { 195 return new Long(getIntx()).toString(); 196 } else if (isUIntx()) { 197 return new Long(getUIntx()).toString(); 198 } else { 199 return null; 200 } 201 } 202 }; 203 204 private static void checkVMVersion(String vmRelease) { 205 if (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null) { 206 // read sa build version. 207 String versionProp = "sun.jvm.hotspot.runtime.VM.saBuildVersion"; 208 String saVersion = saProps.getProperty(versionProp); 209 if (saVersion == null) 210 throw new RuntimeException("Missing property " + versionProp); 211 212 // Strip nonproduct VM version substring (note: saVersion doesn't have it). 213 String vmVersion = vmRelease.replaceAll("(-fastdebug)|(-debug)|(-jvmg)|(-optimized)|(-profiled)",""); 214 215 if (saVersion.equals(vmVersion)) { 216 // Exact match 217 return; 218 } 219 if (saVersion.indexOf('-') == saVersion.lastIndexOf('-') && 220 vmVersion.indexOf('-') == vmVersion.lastIndexOf('-')) { 221 // Throw exception if different release versions: 222 // <major>.<minor>-b<n> 223 throw new VMVersionMismatchException(saVersion, vmRelease); 224 } else { 225 // Otherwise print warning to allow mismatch not release versions 226 // during development. 227 System.err.println("WARNING: Hotspot VM version " + vmRelease + 228 " does not match with SA version " + saVersion + 229 "." + " You may see unexpected results. "); 230 } 231 } else { 232 System.err.println("WARNING: You have disabled SA and VM version check. You may be " + 233 "using incompatible version of SA and you may see unexpected " + 234 "results."); 235 } 236 } 237 238 private static final boolean disableDerivedPrinterTableCheck; 239 private static final Properties saProps; 240 241 static { 242 saProps = new Properties(); 243 URL url = null; 244 try { 245 url = VM.class.getClassLoader().getResource("sa.properties"); 246 saProps.load(new BufferedInputStream(url.openStream())); 247 } catch (Exception e) { 248 throw new RuntimeException("Unable to load properties " + 249 (url == null ? "null" : url.toString()) + 250 ": " + e.getMessage()); 251 } 252 253 disableDerivedPrinterTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null; 254 } 255 256 private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { 257 this.db = db; 258 this.debugger = debugger; 259 this.isBigEndian = isBigEndian; 260 261 // Note that we don't construct universe, heap, threads, 262 // interpreter, or stubRoutines here (any more). The current 263 // initialization mechanisms require that the VM be completely set 264 // up (i.e., out of its constructor, with soleInstance assigned) 265 // before their static initializers are run. 266 267 if (db.getAddressSize() == 4) { 268 logAddressSize = 2; 269 } else if (db.getAddressSize() == 8) { 270 logAddressSize = 3; 271 } else { 272 throw new RuntimeException("Address size " + db.getAddressSize() + " not yet supported"); 273 } 274 275 // read VM version info 276 try { 277 Type vmVersion = db.lookupType("Abstract_VM_Version"); 278 Address releaseAddr = vmVersion.getAddressField("_s_vm_release").getValue(); 279 vmRelease = CStringUtilities.getString(releaseAddr); 280 Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); 281 vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); 282 } catch (Exception exp) { 283 throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); 284 } 285 286 checkVMVersion(vmRelease); 287 288 stackBias = db.lookupIntConstant("STACK_BIAS").intValue(); 289 invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue(); 290 invalidOSREntryBCI = db.lookupIntConstant("InvalidOSREntryBci").intValue(); 291 292 // We infer the presence of C1 or C2 from a couple of fields we 293 // already have present in the type database 294 { 295 Type type = db.lookupType("methodOopDesc"); 296 if (type.getField("_from_compiled_entry", false, false) == null) { 297 // Neither C1 nor C2 is present 298 usingClientCompiler = false; 299 usingServerCompiler = false; 300 } else { 301 // Determine whether C2 is present 302 if (type.getField("_interpreter_invocation_count", false, false) != null) { 303 usingServerCompiler = true; 304 } else { 305 usingClientCompiler = true; 306 } 307 } 308 } 309 310 useTLAB = (db.lookupIntConstant("UseTLAB").intValue() != 0); 311 312 if (debugger != null) { 313 isLP64 = debugger.getMachineDescription().isLP64(); 314 } 315 bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue(); 316 minObjAlignmentInBytes = db.lookupIntConstant("MinObjAlignmentInBytes").intValue(); 317 // minObjAlignment = db.lookupIntConstant("MinObjAlignment").intValue(); 318 logMinObjAlignmentInBytes = db.lookupIntConstant("LogMinObjAlignmentInBytes").intValue(); 319 heapWordSize = db.lookupIntConstant("HeapWordSize").intValue(); 320 oopSize = db.lookupIntConstant("oopSize").intValue(); 321 322 intxType = db.lookupType("intx"); 323 uintxType = db.lookupType("uintx"); 324 boolType = (CIntegerType) db.lookupType("bool"); 325 326 if (isCompressedOopsEnabled()) { 327 // Size info for oops within java objects is fixed 328 heapOopSize = (int)getIntSize(); 329 } else { 330 heapOopSize = (int)getOopSize(); 331 } 332 } 333 334 /** This could be used by a reflective runtime system */ 335 public static void initialize(TypeDataBase db, boolean isBigEndian) { 336 if (soleInstance != null) { 337 throw new RuntimeException("Attempt to initialize VM twice"); 338 } 339 soleInstance = new VM(db, null, isBigEndian); 340 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 341 ((Observer) iter.next()).update(null, null); 342 } 343 } 344 345 /** This is used by the debugging system */ 346 public static void initialize(TypeDataBase db, JVMDebugger debugger) { 347 if (soleInstance != null) { 348 throw new RuntimeException("Attempt to initialize VM twice"); 349 } 350 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); 351 352 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 353 ((Observer) iter.next()).update(null, null); 354 } 355 356 debugger.putHeapConst(soleInstance.getHeapOopSize(), Universe.getNarrowOopBase(), 357 Universe.getNarrowOopShift()); 358 } 359 360 /** This is used by the debugging system */ 361 public static void shutdown() { 362 soleInstance = null; 363 } 364 365 /** This is used by both the debugger and any runtime system. It is 366 the basic mechanism by which classes which mimic underlying VM 367 functionality cause themselves to be initialized. The given 368 observer will be notified (with arguments (null, null)) when the 369 VM is re-initialized, as well as when it registers itself with 370 the VM. */ 371 public static void registerVMInitializedObserver(Observer o) { 372 vmInitializedObservers.add(o); 373 o.update(null, null); 374 } 375 376 /** This is the primary accessor used by both the debugger and any 377 potential runtime system */ 378 public static VM getVM() { 379 if (soleInstance == null) { 380 throw new RuntimeException("VM.initialize() was not yet called"); 381 } 382 return soleInstance; 383 } 384 385 /** This is only used by the debugging system. The given observer 386 will be notified if the underlying VM resumes execution. NOTE 387 that the given observer is not triggered if the VM is currently 388 running and therefore differs in behavior from {@link 389 #registerVMInitializedObserver} (because of the possibility of 390 race conditions if the observer is added while the VM is being 391 suspended or resumed). */ 392 public void registerVMResumedObserver(Observer o) { 393 vmResumedObservers.add(o); 394 } 395 396 /** This is only used by the debugging system. The given observer 397 will be notified if the underlying VM suspends execution. NOTE 398 that the given observer is not triggered if the VM is currently 399 suspended and therefore differs in behavior from {@link 400 #registerVMInitializedObserver} (because of the possibility of 401 race conditions if the observer is added while the VM is being 402 suspended or resumed). */ 403 public void registerVMSuspendedObserver(Observer o) { 404 vmSuspendedObservers.add(o); 405 } 406 407 /** This is only used by the debugging system. Informs all 408 registered resumption observers that the VM has been resumed. 409 The application is responsible for actually having performed the 410 resumption. No OopHandles must be used after this point, as they 411 may move in the target address space due to garbage 412 collection. */ 413 public void fireVMResumed() { 414 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) { 415 ((Observer) iter.next()).update(null, null); 416 } 417 } 418 419 /** This is only used by the debugging system. Informs all 420 registered suspension observers that the VM has been suspended. 421 The application is responsible for actually having performed the 422 suspension. Garbage collection must be forbidden at this point; 423 for example, a JPDA-level suspension is not adequate since the 424 VM thread may still be running. */ 425 public void fireVMSuspended() { 426 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) { 427 ((Observer) iter.next()).update(null, null); 428 } 429 } 430 431 /** Returns the OS this VM is running on. Notice that by delegating 432 to the debugger we can transparently support remote 433 debugging. */ 434 public String getOS() { 435 if (debugger != null) { 436 return debugger.getOS(); 437 } 438 return PlatformInfo.getOS(); 439 } 440 441 /** Returns the CPU this VM is running on. Notice that by delegating 442 to the debugger we can transparently support remote 443 debugging. */ 444 public String getCPU() { 445 if (debugger != null) { 446 return debugger.getCPU(); 447 } 448 return PlatformInfo.getCPU(); 449 } 450 451 public Type lookupType(String cTypeName) { 452 return db.lookupType(cTypeName); 453 } 454 455 public Integer lookupIntConstant(String name) { 456 return db.lookupIntConstant(name); 457 } 458 459 public long getAddressSize() { 460 return db.getAddressSize(); 461 } 462 463 public long getOopSize() { 464 return oopSize; 465 } 466 467 public long getLogAddressSize() { 468 return logAddressSize; 469 } 470 471 public long getIntSize() { 472 return db.getJIntType().getSize(); 473 } 474 475 /** NOTE: this offset is in BYTES in this system! */ 476 public long getStackBias() { 477 return stackBias; 478 } 479 480 /** Indicates whether the underlying machine supports the LP64 data 481 model. This is needed for conditionalizing code in a few places */ 482 public boolean isLP64() { 483 if (Assert.ASSERTS_ENABLED) { 484 Assert.that(isDebugging(), "Debugging system only for now"); 485 } 486 return isLP64; 487 } 488 489 /** Get bytes-per-long == long/double natural alignment. */ 490 public int getBytesPerLong() { 491 return bytesPerLong; 492 } 493 494 /** Get minimum object alignment in bytes. */ 495 public int getMinObjAlignment() { 496 return minObjAlignmentInBytes; 497 } 498 499 public int getMinObjAlignmentInBytes() { 500 return minObjAlignmentInBytes; 501 } 502 public int getLogMinObjAlignmentInBytes() { 503 return logMinObjAlignmentInBytes; 504 } 505 506 public int getHeapWordSize() { 507 return heapWordSize; 508 } 509 510 public int getHeapOopSize() { 511 return heapOopSize; 512 } 513 /** Utility routine for getting data structure alignment correct */ 514 public long alignUp(long size, long alignment) { 515 return (size + alignment - 1) & ~(alignment - 1); 516 } 517 518 /** Utility routine for getting data structure alignment correct */ 519 public long alignDown(long size, long alignment) { 520 return size & ~(alignment - 1); 521 } 522 523 /** Utility routine for building an int from two "unsigned" 16-bit 524 shorts */ 525 public int buildIntFromShorts(short low, short high) { 526 return (((int) high) << 16) | (((int) low) & 0xFFFF); 527 } 528 529 /** Utility routine for building a long from two "unsigned" 32-bit 530 ints in <b>platform-dependent</b> order */ 531 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 532 if (isBigEndian) { 533 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 534 } else{ 535 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 536 } 537 } 538 539 /** Indicates whether Thread-Local Allocation Buffers are used */ 540 public boolean getUseTLAB() { 541 return useTLAB; 542 } 543 544 public TypeDataBase getTypeDataBase() { 545 return db; 546 } 547 548 public Universe getUniverse() { 549 if (universe == null) { 550 universe = new Universe(); 551 } 552 return universe; 553 } 554 555 public ObjectHeap getObjectHeap() { 556 if (heap == null) { 557 heap = new ObjectHeap(db); 558 } 559 return heap; 560 } 561 562 public SymbolTable getSymbolTable() { 563 if (symbols == null) { 564 symbols = SymbolTable.getTheTable(); 565 } 566 return symbols; 567 } 568 569 public StringTable getStringTable() { 570 if (strings == null) { 571 strings = StringTable.getTheTable(); 572 } 573 return strings; 574 } 575 576 public SystemDictionary getSystemDictionary() { 577 if (dict == null) { 578 dict = new SystemDictionary(); 579 } 580 return dict; 581 } 582 583 public Threads getThreads() { 584 if (threads == null) { 585 threads = new Threads(); 586 } 587 return threads; 588 } 589 590 public ObjectSynchronizer getObjectSynchronizer() { 591 if (synchronizer == null) { 592 synchronizer = new ObjectSynchronizer(); 593 } 594 return synchronizer; 595 } 596 597 public JNIHandles getJNIHandles() { 598 if (handles == null) { 599 handles = new JNIHandles(); 600 } 601 return handles; 602 } 603 604 public Interpreter getInterpreter() { 605 if (interpreter == null) { 606 interpreter = new Interpreter(); 607 } 608 return interpreter; 609 } 610 611 public StubRoutines getStubRoutines() { 612 if (stubRoutines == null) { 613 stubRoutines = new StubRoutines(); 614 } 615 return stubRoutines; 616 } 617 618 public VMRegImpl getVMRegImplInfo() { 619 if (vmregImpl == null) { 620 vmregImpl = new VMRegImpl(); 621 } 622 return vmregImpl; 623 } 624 625 public Bytes getBytes() { 626 if (bytes == null) { 627 bytes = new Bytes(debugger.getMachineDescription()); 628 } 629 return bytes; 630 } 631 632 /** Returns true if this is a isBigEndian, false otherwise */ 633 public boolean isBigEndian() { 634 return isBigEndian; 635 } 636 637 /** Returns true if this is a "core" build, false if either C1 or C2 638 is present */ 639 public boolean isCore() { 640 return (!(usingClientCompiler || usingServerCompiler)); 641 } 642 643 /** Returns true if this is a C1 build, false otherwise */ 644 public boolean isClientCompiler() { 645 return usingClientCompiler; 646 } 647 648 /** Returns true if this is a C2 build, false otherwise */ 649 public boolean isServerCompiler() { 650 return usingServerCompiler; 651 } 652 653 /** Returns true if C2 derived pointer table should be used, false otherwise */ 654 public boolean useDerivedPointerTable() { 655 return !disableDerivedPrinterTableCheck; 656 } 657 658 /** Returns the code cache; should not be used if is core build */ 659 public CodeCache getCodeCache() { 660 if (Assert.ASSERTS_ENABLED) { 661 Assert.that(!isCore(), "noncore builds only"); 662 } 663 if (codeCache == null) { 664 codeCache = new CodeCache(); 665 } 666 return codeCache; 667 } 668 669 /** Should only be called for C1 builds */ 670 public Runtime1 getRuntime1() { 671 if (Assert.ASSERTS_ENABLED) { 672 Assert.that(isClientCompiler(), "C1 builds only"); 673 } 674 if (runtime1 == null) { 675 runtime1 = new Runtime1(); 676 } 677 return runtime1; 678 } 679 680 /** Test to see whether we're in debugging mode (NOTE: this really 681 should not be tested by this code; currently only used in 682 StackFrameStream) */ 683 public boolean isDebugging() { 684 return (debugger != null); 685 } 686 687 /** This is only used by the debugging (i.e., non-runtime) system */ 688 public JVMDebugger getDebugger() { 689 if (debugger == null) { 690 throw new RuntimeException("Attempt to use debugger in runtime system"); 691 } 692 return debugger; 693 } 694 695 /** Indicates whether a given program counter is in Java code. This 696 includes but is not spanned by the interpreter and code cache. 697 Only used in the debugging system, for implementing 698 JavaThread.currentFrameGuess() on x86. */ 699 public boolean isJavaPCDbg(Address addr) { 700 // FIXME: this is not a complete enough set: must include areas 701 // like vtable stubs 702 return (getInterpreter().contains(addr) || 703 getCodeCache().contains(addr)); 704 } 705 706 /** FIXME: figure out where to stick this */ 707 public int getInvocationEntryBCI() { 708 return invocationEntryBCI; 709 } 710 711 /** FIXME: figure out where to stick this */ 712 public int getInvalidOSREntryBCI() { 713 return invalidOSREntryBCI; 714 } 715 716 // FIXME: figure out where to stick this 717 public boolean wizardMode() { 718 return true; 719 } 720 721 public ReversePtrs getRevPtrs() { 722 return revPtrs; 723 } 724 725 public void setRevPtrs(ReversePtrs rp) { 726 revPtrs = rp; 727 } 728 729 // returns null, if not available. 730 public String getVMRelease() { 731 return vmRelease; 732 } 733 734 // returns null, if not available. 735 public String getVMInternalInfo() { 736 return vmInternalInfo; 737 } 738 739 public boolean isSharingEnabled() { 740 if (sharingEnabled == null) { 741 Flag flag = getCommandLineFlag("UseSharedSpaces"); 742 sharingEnabled = (flag == null)? Boolean.FALSE : 743 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 744 } 745 return sharingEnabled.booleanValue(); 746 } 747 748 public boolean isCompressedOopsEnabled() { 749 if (compressedOopsEnabled == null) { 750 Flag flag = getCommandLineFlag("UseCompressedOops"); 751 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 752 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 753 } 754 return compressedOopsEnabled.booleanValue(); 755 } 756 757 // returns null, if not available. 758 public Flag[] getCommandLineFlags() { 759 if (commandLineFlags == null) { 760 readCommandLineFlags(); 761 } 762 763 return commandLineFlags; 764 } 765 766 public Flag getCommandLineFlag(String name) { 767 if (flagsMap == null) { 768 flagsMap = new HashMap(); 769 Flag[] flags = getCommandLineFlags(); 770 for (int i = 0; i < flags.length; i++) { 771 flagsMap.put(flags[i].getName(), flags[i]); 772 } 773 } 774 return (Flag) flagsMap.get(name); 775 } 776 777 private void readCommandLineFlags() { 778 // get command line flags 779 TypeDataBase db = getTypeDataBase(); 780 try { 781 Type flagType = db.lookupType("Flag"); 782 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 783 // NOTE: last flag contains null values. 784 commandLineFlags = new Flag[numFlags - 1]; 785 786 Address flagAddr = flagType.getAddressField("flags").getValue(); 787 788 AddressField typeFld = flagType.getAddressField("type"); 789 AddressField nameFld = flagType.getAddressField("name"); 790 AddressField addrFld = flagType.getAddressField("addr"); 791 AddressField kindFld = flagType.getAddressField("kind"); 792 793 long flagSize = flagType.getSize(); // sizeof(Flag) 794 795 // NOTE: last flag contains null values. 796 for (int f = 0; f < numFlags - 1; f++) { 797 String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); 798 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 799 Address addr = addrFld.getValue(flagAddr); 800 String kind = CStringUtilities.getString(kindFld.getValue(flagAddr)); 801 commandLineFlags[f] = new Flag(type, name, addr, kind); 802 flagAddr = flagAddr.addOffsetTo(flagSize); 803 } 804 805 // sort flags by name 806 Arrays.sort(commandLineFlags, new Comparator() { 807 public int compare(Object o1, Object o2) { 808 Flag f1 = (Flag) o1; 809 Flag f2 = (Flag) o2; 810 return f1.getName().compareTo(f2.getName()); 811 } 812 }); 813 } catch (Exception exp) { 814 // ignore. may be older version. command line flags not available. 815 } 816 } 817 818 public String getSystemProperty(String key) { 819 Properties props = getSystemProperties(); 820 return (props != null)? props.getProperty(key) : null; 821 } 822 823 public Properties getSystemProperties() { 824 if (sysProps == null) { 825 readSystemProperties(); 826 } 827 return sysProps; 828 } 829 830 private void readSystemProperties() { 831 InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 832 systemKls.iterate(new DefaultOopVisitor() { 833 ObjectReader objReader = new ObjectReader(); 834 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 835 if (field.getID().getName().equals("props")) { 836 try { 837 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 838 } catch (Exception e) { 839 if (Assert.ASSERTS_ENABLED) { 840 e.printStackTrace(); 841 } 842 } 843 } 844 } 845 }, false); 846 } 847 }