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