1 /* 2 * Copyright 2000-2008 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; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.types.*; 31 import sun.jvm.hotspot.types.basic.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 /** <P> This is the cross-platform TypeDataBase used by the Oop 35 hierarchy. The decision was made to make this cross-platform by 36 having the VM export the necessary symbols via a built-in table; 37 see src/share/vm/runtime/vmStructs.[ch]pp for more details. </P> 38 39 <P> <B>WARNING</B>: clients should refer to this class through the 40 TypeDataBase interface and not directly to the HotSpotTypeDataBase 41 type. </P> 42 43 <P> NOTE: since we are fetching the sizes of the Java primitive types 44 */ 45 46 public class HotSpotTypeDataBase extends BasicTypeDataBase { 47 private Debugger symbolLookup; 48 private String[] jvmLibNames; 49 private static final int UNINITIALIZED_SIZE = -1; 50 private static final int C_INT8_SIZE = 1; 51 private static final int C_INT32_SIZE = 4; 52 private static final int C_INT64_SIZE = 8; 53 54 private static final boolean DEBUG; 55 static { 56 DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG") 57 != null; 58 } 59 60 /** <P> This requires a SymbolLookup mechanism as well as the 61 MachineDescription. Note that we do not need a NameMangler since 62 we use the vmStructs mechanism to avoid looking up C++ 63 symbols. </P> 64 65 <P> NOTE that it is guaranteed that this constructor will not 66 attempt to fetch any Java values from the remote process, only C 67 integers and addresses. This is required because we are fetching 68 the sizes of the Java primitive types from the remote process, 69 implying that attempting to fetch them before their sizes are 70 known is illegal. </P> 71 72 <P> Throws NoSuchSymbolException if a problem occurred while 73 looking up one of the bootstrapping symbols related to the 74 VMStructs table in the remote VM; this may indicate that the 75 remote process is not actually a HotSpot VM. </P> 76 */ 77 public HotSpotTypeDataBase(MachineDescription machDesc, 78 VtblAccess vtblAccess, 79 Debugger symbolLookup, 80 String[] jvmLibNames) throws NoSuchSymbolException { 81 super(machDesc, vtblAccess); 82 this.symbolLookup = symbolLookup; 83 this.jvmLibNames = jvmLibNames; 84 85 readVMTypes(); 86 initializePrimitiveTypes(); 87 readVMStructs(); 88 readVMIntConstants(); 89 readVMLongConstants(); 90 } 91 92 private void readVMTypes() { 93 // Get the variables we need in order to traverse the VMTypeEntry[] 94 long typeEntryTypeNameOffset; 95 long typeEntrySuperclassNameOffset; 96 long typeEntryIsOopTypeOffset; 97 long typeEntryIsIntegerTypeOffset; 98 long typeEntryIsUnsignedOffset; 99 long typeEntrySizeOffset; 100 long typeEntryArrayStride; 101 102 typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); 103 typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); 104 typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); 105 typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); 106 typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); 107 typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); 108 typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); 109 110 // Fetch the address of the VMTypeEntry* 111 Address entryAddr = lookupInProcess("gHotSpotVMTypes"); 112 // System.err.println("gHotSpotVMTypes address = " + entryAddr); 113 // Dereference this once to get the pointer to the first VMTypeEntry 114 // dumpMemory(entryAddr, 80); 115 entryAddr = entryAddr.getAddressAt(0); 116 117 if (entryAddr == null) { 118 throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); 119 } 120 121 // Start iterating down it until we find an entry with no name 122 Address typeNameAddr = null; 123 do { 124 // Fetch the type name first 125 typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset); 126 if (typeNameAddr != null) { 127 String typeName = CStringUtilities.getString(typeNameAddr); 128 129 String superclassName = null; 130 Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset); 131 if (superclassNameAddr != null) { 132 superclassName = CStringUtilities.getString(superclassNameAddr); 133 } 134 135 boolean isOopType = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0); 136 boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0); 137 boolean isUnsigned = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0); 138 long size = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true); 139 140 createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size); 141 } 142 143 entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); 144 } while (typeNameAddr != null); 145 } 146 147 private void initializePrimitiveTypes() { 148 // Look up the needed primitive types by name...they had better be present 149 setJBooleanType(lookupPrimitiveType("jboolean")); 150 setJByteType (lookupPrimitiveType("jbyte")); 151 setJCharType (lookupPrimitiveType("jchar")); 152 setJDoubleType (lookupPrimitiveType("jdouble")); 153 setJFloatType (lookupPrimitiveType("jfloat")); 154 setJIntType (lookupPrimitiveType("jint")); 155 setJLongType (lookupPrimitiveType("jlong")); 156 setJShortType (lookupPrimitiveType("jshort")); 157 158 // Indicate that these are the Java primitive types 159 ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true); 160 ((BasicType) getJByteType()).setIsJavaPrimitiveType(true); 161 ((BasicType) getJCharType()).setIsJavaPrimitiveType(true); 162 ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true); 163 ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true); 164 ((BasicType) getJIntType()).setIsJavaPrimitiveType(true); 165 ((BasicType) getJLongType()).setIsJavaPrimitiveType(true); 166 ((BasicType) getJShortType()).setIsJavaPrimitiveType(true); 167 } 168 169 private Type lookupPrimitiveType(String typeName) { 170 Type type = lookupType(typeName, false); 171 if (type == null) { 172 throw new RuntimeException("Error initializing the HotSpotDataBase: could not find the primitive type \"" + 173 typeName + "\" in the remote VM's VMStructs table. This type is required in " + 174 "order to determine the size of Java primitive types. Can not continue."); 175 } 176 return type; 177 } 178 179 private void readVMStructs() { 180 // Get the variables we need in order to traverse the VMStructEntry[] 181 long structEntryTypeNameOffset; 182 long structEntryFieldNameOffset; 183 long structEntryTypeStringOffset; 184 long structEntryIsStaticOffset; 185 long structEntryOffsetOffset; 186 long structEntryAddressOffset; 187 long structEntryArrayStride; 188 189 structEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset"); 190 structEntryFieldNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset"); 191 structEntryTypeStringOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset"); 192 structEntryIsStaticOffset = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset"); 193 structEntryOffsetOffset = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset"); 194 structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); 195 structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); 196 197 // Fetch the address of the VMStructEntry* 198 Address entryAddr = lookupInProcess("gHotSpotVMStructs"); 199 // Dereference this once to get the pointer to the first VMStructEntry 200 entryAddr = entryAddr.getAddressAt(0); 201 if (entryAddr == null) { 202 throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue"); 203 } 204 205 // Start iterating down it until we find an entry with no name 206 Address fieldNameAddr = null; 207 String typeName = null; 208 String fieldName = null; 209 String typeString = null; 210 boolean isStatic = false; 211 long offset = 0; 212 Address staticFieldAddr = null; 213 long size = 0; 214 long index = 0; 215 String opaqueName = "<opaque>"; 216 lookupOrCreateClass(opaqueName, false, false, false); 217 218 do { 219 // Fetch the field name first 220 fieldNameAddr = entryAddr.getAddressAt(structEntryFieldNameOffset); 221 if (fieldNameAddr != null) { 222 fieldName = CStringUtilities.getString(fieldNameAddr); 223 224 // Now the rest of the names. Keep in mind that the type name 225 // may be NULL, indicating that the type is opaque. 226 Address addr = entryAddr.getAddressAt(structEntryTypeNameOffset); 227 if (addr == null) { 228 throw new RuntimeException("gHotSpotVMStructs unexpectedly had a NULL type name at index " + index); 229 } 230 typeName = CStringUtilities.getString(addr); 231 232 addr = entryAddr.getAddressAt(structEntryTypeStringOffset); 233 if (addr == null) { 234 typeString = opaqueName; 235 } else { 236 typeString = CStringUtilities.getString(addr); 237 } 238 239 isStatic = !(entryAddr.getCIntegerAt(structEntryIsStaticOffset, C_INT32_SIZE, false) == 0); 240 if (isStatic) { 241 staticFieldAddr = entryAddr.getAddressAt(structEntryAddressOffset); 242 offset = 0; 243 } else { 244 offset = entryAddr.getCIntegerAt(structEntryOffsetOffset, C_INT64_SIZE, true); 245 staticFieldAddr = null; 246 } 247 248 // The containing Type must already be in the database -- no exceptions 249 BasicType containingType = lookupOrFail(typeName); 250 251 // The field's Type must already be in the database -- no exceptions 252 BasicType fieldType = lookupOrFail(typeString); 253 254 // Create field by type 255 createField(containingType, fieldName, fieldType, 256 isStatic, offset, staticFieldAddr); 257 } 258 259 ++index; 260 entryAddr = entryAddr.addOffsetTo(structEntryArrayStride); 261 } while (fieldNameAddr != null); 262 } 263 264 private void readVMIntConstants() { 265 // Get the variables we need in order to traverse the VMIntConstantEntry[] 266 long intConstantEntryNameOffset; 267 long intConstantEntryValueOffset; 268 long intConstantEntryArrayStride; 269 270 intConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset"); 271 intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); 272 intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); 273 274 // Fetch the address of the VMIntConstantEntry* 275 Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); 276 // Dereference this once to get the pointer to the first VMIntConstantEntry 277 entryAddr = entryAddr.getAddressAt(0); 278 if (entryAddr == null) { 279 throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue"); 280 } 281 282 // Start iterating down it until we find an entry with no name 283 Address nameAddr = null; 284 do { 285 // Fetch the type name first 286 nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset); 287 if (nameAddr != null) { 288 String name = CStringUtilities.getString(nameAddr); 289 int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false); 290 291 // Be a little resilient 292 Integer oldValue = lookupIntConstant(name, false); 293 if (oldValue == null) { 294 addIntConstant(name, value); 295 } else { 296 if (oldValue.intValue() != value) { 297 throw new RuntimeException("Error: the integer constant \"" + name + 298 "\" had its value redefined (old was " + oldValue + 299 ", new is " + value + ". Aborting."); 300 } else { 301 System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + 302 "had its value declared as " + value + " twice. Continuing."); 303 } 304 } 305 } 306 307 entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); 308 } while (nameAddr != null); 309 String symbol = "heapOopSize"; // global int constant and value is initialized at runtime. 310 addIntConstant(symbol, (int)lookupInProcess(symbol).getCIntegerAt(0, 4, false)); 311 } 312 313 private void readVMLongConstants() { 314 // Get the variables we need in order to traverse the VMLongConstantEntry[] 315 long longConstantEntryNameOffset; 316 long longConstantEntryValueOffset; 317 long longConstantEntryArrayStride; 318 319 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); 320 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); 321 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); 322 323 // Fetch the address of the VMLongConstantEntry* 324 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); 325 // Dereference this once to get the pointer to the first VMLongConstantEntry 326 entryAddr = entryAddr.getAddressAt(0); 327 if (entryAddr == null) { 328 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); 329 } 330 331 // Start iterating down it until we find an entry with no name 332 Address nameAddr = null; 333 do { 334 // Fetch the type name first 335 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); 336 if (nameAddr != null) { 337 String name = CStringUtilities.getString(nameAddr); 338 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); 339 340 // Be a little resilient 341 Long oldValue = lookupLongConstant(name, false); 342 if (oldValue == null) { 343 addLongConstant(name, value); 344 } else { 345 if (oldValue.longValue() != value) { 346 throw new RuntimeException("Error: the long constant \"" + name + 347 "\" had its value redefined (old was " + oldValue + 348 ", new is " + value + ". Aborting."); 349 } else { 350 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + 351 "had its value declared as " + value + " twice. Continuing."); 352 } 353 } 354 } 355 356 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); 357 } while (nameAddr != null); 358 } 359 360 private BasicType lookupOrFail(String typeName) { 361 BasicType type = (BasicType) lookupType(typeName, false); 362 if (type == null) { 363 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + 364 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + 365 "in the debug build of that VM). Can not continue."); 366 } 367 return type; 368 } 369 370 private long getLongValueFromProcess(String symbol) { 371 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); 372 } 373 374 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { 375 // FIXME: abstract away the loadobject name 376 for (int i = 0; i < jvmLibNames.length; i++) { 377 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); 378 if (addr != null) { 379 return addr; 380 } 381 } 382 String errStr = "("; 383 for (int i = 0; i < jvmLibNames.length; i++) { 384 errStr += jvmLibNames[i]; 385 if (i < jvmLibNames.length - 1) { 386 errStr += ", "; 387 } 388 } 389 errStr += ")"; 390 throw new NoSuchSymbolException(symbol, 391 "Could not find symbol \"" + symbol + 392 "\" in any of the known library names " + 393 errStr); 394 } 395 396 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, 397 boolean isIntegerType, boolean isUnsigned) { 398 BasicType type = (BasicType) lookupType(typeName, false); 399 if (type == null) { 400 // Create a new type 401 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); 402 } 403 return type; 404 } 405 406 /** Creates a new BasicType, initializes its size to -1 so we can 407 test to ensure that all types' sizes are initialized by VMTypes, 408 and adds it to the database. Takes care of initializing integer 409 and oop types properly. */ 410 private BasicType createBasicType(String typeName, boolean isOopType, 411 boolean isIntegerType, boolean isUnsigned) { 412 413 BasicType type = null; 414 415 if (isIntegerType) { 416 type = new BasicCIntegerType(this, typeName, isUnsigned); 417 } else { 418 if (typeNameIsPointerType(typeName)) { 419 type = recursiveCreateBasicPointerType(typeName); 420 } else { 421 type = new BasicType(this, typeName); 422 } 423 424 if (isOopType) { 425 // HACK: turn markOop into a C integer type. This allows 426 // proper handling of it in the Serviceability Agent. (FIXME 427 // -- consider doing something different here) 428 if (typeName.equals("markOop")) { 429 type = new BasicCIntegerType(this, typeName, true); 430 } else { 431 type.setIsOopType(true); 432 } 433 } 434 } 435 436 type.setSize(UNINITIALIZED_SIZE); 437 addType(type); 438 return type; 439 } 440 441 /** Recursively creates a PointerType from the string representation 442 of the type's name. Note that this currently needs some 443 workarounds due to incomplete information in the VMStructs 444 database. */ 445 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { 446 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); 447 Type targetType = null; 448 if (typeNameIsPointerType(targetTypeName)) { 449 targetType = recursiveCreateBasicPointerType(targetTypeName); 450 } else { 451 targetType = lookupType(targetTypeName, false); 452 if (targetType == null) { 453 // Workaround for missing C integer types in database. 454 // Also looks like we can't throw an exception for other 455 // missing target types because there are some in old 456 // VMStructs tables that didn't have the target type declared. 457 // For this case, we create basic types that never get filled 458 // in. 459 460 if (targetTypeName.equals("char") || 461 targetTypeName.equals("const char")) { 462 // We don't have a representation of const-ness of C types in the SA 463 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); 464 basicTargetType.setSize(1); 465 targetType = basicTargetType; 466 } else if (targetTypeName.equals("u_char")) { 467 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); 468 basicTargetType.setSize(1); 469 targetType = basicTargetType; 470 } else { 471 if (DEBUG) { 472 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); 473 } 474 targetType = createBasicType(targetTypeName, false, false, false); 475 } 476 } 477 } 478 return new BasicPointerType(this, typeName, targetType); 479 } 480 481 private boolean typeNameIsPointerType(String typeName) { 482 int i = typeName.length() - 1; 483 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { 484 --i; 485 } 486 if (i >= 0 && typeName.charAt(i) == '*') { 487 return true; 488 } 489 return false; 490 } 491 492 public void createType(String typeName, String superclassName, 493 boolean isOopType, boolean isIntegerType, 494 boolean isUnsigned, long size) { 495 // See whether we have a superclass 496 BasicType superclass = null; 497 if (superclassName != null) { 498 // Fetch or create it (FIXME: would get oop types wrong if 499 // they had a hierarchy; consider using lookupOrFail) 500 superclass = lookupOrCreateClass(superclassName, false, false, false); 501 } 502 503 // Lookup or create the current type 504 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); 505 // Set superclass and/or ensure it's correct 506 if (superclass != null) { 507 if (curType.getSuperclass() == null) { 508 // Set the superclass in the current type 509 curType.setSuperclass(superclass); 510 } 511 512 if (curType.getSuperclass() != superclass) { 513 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 514 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + 515 superclass.getName() + ")."); 516 } 517 } 518 519 // Classes are created with a size of UNINITIALIZED_SIZE. 520 // Set size if necessary. 521 if (curType.getSize() == UNINITIALIZED_SIZE) { 522 curType.setSize(size); 523 } else { 524 if (curType.getSize() != size) { 525 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 526 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); 527 } 528 529 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 530 "had its size declared as " + size + " twice. Continuing."); 531 } 532 533 } 534 535 /** "Virtual constructor" for fields based on type */ 536 public void createField(BasicType containingType, 537 String name, Type type, boolean isStatic, 538 long offset, Address staticFieldAddress) { 539 // Add field to containing type 540 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); 541 } 542 543 Field internalCreateField(BasicType containingType, 544 String name, Type type, boolean isStatic, 545 long offset, Address staticFieldAddress) { 546 // "Virtual constructor" based on type 547 if (type.isOopType()) { 548 return new BasicOopField(this, containingType, name, type, 549 isStatic, offset, staticFieldAddress); 550 } 551 552 if (type instanceof CIntegerType) { 553 return new BasicCIntegerField(this, containingType, name, type, 554 isStatic, offset, staticFieldAddress); 555 } 556 557 if (type.equals(getJBooleanType())) { 558 return new BasicJBooleanField(this, containingType, name, type, 559 isStatic, offset, staticFieldAddress); 560 } 561 562 if (type.equals(getJByteType())) { 563 return new BasicJByteField(this, containingType, name, type, 564 isStatic, offset, staticFieldAddress); 565 } 566 567 if (type.equals(getJCharType())) { 568 return new BasicJCharField(this, containingType, name, type, 569 isStatic, offset, staticFieldAddress); 570 } 571 572 if (type.equals(getJDoubleType())) { 573 return new BasicJDoubleField(this, containingType, name, type, 574 isStatic, offset, staticFieldAddress); 575 } 576 577 if (type.equals(getJFloatType())) { 578 return new BasicJFloatField(this, containingType, name, type, 579 isStatic, offset, staticFieldAddress); 580 } 581 582 if (type.equals(getJIntType())) { 583 return new BasicJIntField(this, containingType, name, type, 584 isStatic, offset, staticFieldAddress); 585 } 586 587 if (type.equals(getJLongType())) { 588 return new BasicJLongField(this, containingType, name, type, 589 isStatic, offset, staticFieldAddress); 590 } 591 592 if (type.equals(getJShortType())) { 593 return new BasicJShortField(this, containingType, name, type, 594 isStatic, offset, staticFieldAddress); 595 } 596 597 // Unknown ("opaque") type. Instantiate ordinary Field. 598 return new BasicField(this, containingType, name, type, 599 isStatic, offset, staticFieldAddress); 600 } 601 602 // For debugging 603 private void dumpMemory(Address addr, int len) { 604 int i = 0; 605 while (i < len) { 606 System.err.print(addr.addOffsetTo(i) + ":"); 607 for (int j = 0; j < 8 && i < len; i++, j++) { 608 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); 609 System.err.print(" 0x"); 610 for (int k = 0; k < 2 - s.length(); k++) { 611 System.err.print("0"); 612 } 613 System.err.print(s); 614 } 615 System.err.println(); 616 } 617 } 618 }