1 /* 2 * Copyright (c) 2000, 2009, 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, 20 * CA 94065 USA or visit www.oracle.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 } 310 311 private void readVMLongConstants() { 312 // Get the variables we need in order to traverse the VMLongConstantEntry[] 313 long longConstantEntryNameOffset; 314 long longConstantEntryValueOffset; 315 long longConstantEntryArrayStride; 316 317 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); 318 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); 319 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); 320 321 // Fetch the address of the VMLongConstantEntry* 322 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); 323 // Dereference this once to get the pointer to the first VMLongConstantEntry 324 entryAddr = entryAddr.getAddressAt(0); 325 if (entryAddr == null) { 326 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); 327 } 328 329 // Start iterating down it until we find an entry with no name 330 Address nameAddr = null; 331 do { 332 // Fetch the type name first 333 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); 334 if (nameAddr != null) { 335 String name = CStringUtilities.getString(nameAddr); 336 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); 337 338 // Be a little resilient 339 Long oldValue = lookupLongConstant(name, false); 340 if (oldValue == null) { 341 addLongConstant(name, value); 342 } else { 343 if (oldValue.longValue() != value) { 344 throw new RuntimeException("Error: the long constant \"" + name + 345 "\" had its value redefined (old was " + oldValue + 346 ", new is " + value + ". Aborting."); 347 } else { 348 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + 349 "had its value declared as " + value + " twice. Continuing."); 350 } 351 } 352 } 353 354 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); 355 } while (nameAddr != null); 356 } 357 358 private BasicType lookupOrFail(String typeName) { 359 BasicType type = (BasicType) lookupType(typeName, false); 360 if (type == null) { 361 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + 362 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + 363 "in the debug build of that VM). Can not continue."); 364 } 365 return type; 366 } 367 368 private long getLongValueFromProcess(String symbol) { 369 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); 370 } 371 372 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { 373 // FIXME: abstract away the loadobject name 374 for (int i = 0; i < jvmLibNames.length; i++) { 375 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); 376 if (addr != null) { 377 return addr; 378 } 379 } 380 String errStr = "("; 381 for (int i = 0; i < jvmLibNames.length; i++) { 382 errStr += jvmLibNames[i]; 383 if (i < jvmLibNames.length - 1) { 384 errStr += ", "; 385 } 386 } 387 errStr += ")"; 388 throw new NoSuchSymbolException(symbol, 389 "Could not find symbol \"" + symbol + 390 "\" in any of the known library names " + 391 errStr); 392 } 393 394 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, 395 boolean isIntegerType, boolean isUnsigned) { 396 BasicType type = (BasicType) lookupType(typeName, false); 397 if (type == null) { 398 // Create a new type 399 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); 400 } 401 return type; 402 } 403 404 /** Creates a new BasicType, initializes its size to -1 so we can 405 test to ensure that all types' sizes are initialized by VMTypes, 406 and adds it to the database. Takes care of initializing integer 407 and oop types properly. */ 408 private BasicType createBasicType(String typeName, boolean isOopType, 409 boolean isIntegerType, boolean isUnsigned) { 410 411 BasicType type = null; 412 413 if (isIntegerType) { 414 type = new BasicCIntegerType(this, typeName, isUnsigned); 415 } else { 416 if (typeNameIsPointerType(typeName)) { 417 type = recursiveCreateBasicPointerType(typeName); 418 } else { 419 type = new BasicType(this, typeName); 420 } 421 422 if (isOopType) { 423 // HACK: turn markOop into a C integer type. This allows 424 // proper handling of it in the Serviceability Agent. (FIXME 425 // -- consider doing something different here) 426 if (typeName.equals("markOop")) { 427 type = new BasicCIntegerType(this, typeName, true); 428 } else { 429 type.setIsOopType(true); 430 } 431 } 432 } 433 434 type.setSize(UNINITIALIZED_SIZE); 435 addType(type); 436 return type; 437 } 438 439 /** Recursively creates a PointerType from the string representation 440 of the type's name. Note that this currently needs some 441 workarounds due to incomplete information in the VMStructs 442 database. */ 443 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { 444 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); 445 Type targetType = null; 446 if (typeNameIsPointerType(targetTypeName)) { 447 targetType = recursiveCreateBasicPointerType(targetTypeName); 448 } else { 449 targetType = lookupType(targetTypeName, false); 450 if (targetType == null) { 451 // Workaround for missing C integer types in database. 452 // Also looks like we can't throw an exception for other 453 // missing target types because there are some in old 454 // VMStructs tables that didn't have the target type declared. 455 // For this case, we create basic types that never get filled 456 // in. 457 458 if (targetTypeName.equals("char") || 459 targetTypeName.equals("const char")) { 460 // We don't have a representation of const-ness of C types in the SA 461 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); 462 basicTargetType.setSize(1); 463 targetType = basicTargetType; 464 } else if (targetTypeName.equals("u_char")) { 465 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); 466 basicTargetType.setSize(1); 467 targetType = basicTargetType; 468 } else { 469 if (DEBUG) { 470 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); 471 } 472 targetType = createBasicType(targetTypeName, false, false, false); 473 } 474 } 475 } 476 return new BasicPointerType(this, typeName, targetType); 477 } 478 479 private boolean typeNameIsPointerType(String typeName) { 480 int i = typeName.length() - 1; 481 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { 482 --i; 483 } 484 if (i >= 0 && typeName.charAt(i) == '*') { 485 return true; 486 } 487 return false; 488 } 489 490 public void createType(String typeName, String superclassName, 491 boolean isOopType, boolean isIntegerType, 492 boolean isUnsigned, long size) { 493 // See whether we have a superclass 494 BasicType superclass = null; 495 if (superclassName != null) { 496 // Fetch or create it (FIXME: would get oop types wrong if 497 // they had a hierarchy; consider using lookupOrFail) 498 superclass = lookupOrCreateClass(superclassName, false, false, false); 499 } 500 501 // Lookup or create the current type 502 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); 503 // Set superclass and/or ensure it's correct 504 if (superclass != null) { 505 if (curType.getSuperclass() == null) { 506 // Set the superclass in the current type 507 curType.setSuperclass(superclass); 508 } 509 510 if (curType.getSuperclass() != superclass) { 511 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 512 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + 513 superclass.getName() + ")."); 514 } 515 } 516 517 // Classes are created with a size of UNINITIALIZED_SIZE. 518 // Set size if necessary. 519 if (curType.getSize() == UNINITIALIZED_SIZE) { 520 curType.setSize(size); 521 } else { 522 if (curType.getSize() != size) { 523 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 524 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); 525 } 526 527 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 528 "had its size declared as " + size + " twice. Continuing."); 529 } 530 531 } 532 533 /** "Virtual constructor" for fields based on type */ 534 public void createField(BasicType containingType, 535 String name, Type type, boolean isStatic, 536 long offset, Address staticFieldAddress) { 537 // Add field to containing type 538 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); 539 } 540 541 Field internalCreateField(BasicType containingType, 542 String name, Type type, boolean isStatic, 543 long offset, Address staticFieldAddress) { 544 // "Virtual constructor" based on type 545 if (type.isOopType()) { 546 return new BasicOopField(this, containingType, name, type, 547 isStatic, offset, staticFieldAddress); 548 } 549 550 if (type instanceof CIntegerType) { 551 return new BasicCIntegerField(this, containingType, name, type, 552 isStatic, offset, staticFieldAddress); 553 } 554 555 if (type.equals(getJBooleanType())) { 556 return new BasicJBooleanField(this, containingType, name, type, 557 isStatic, offset, staticFieldAddress); 558 } 559 560 if (type.equals(getJByteType())) { 561 return new BasicJByteField(this, containingType, name, type, 562 isStatic, offset, staticFieldAddress); 563 } 564 565 if (type.equals(getJCharType())) { 566 return new BasicJCharField(this, containingType, name, type, 567 isStatic, offset, staticFieldAddress); 568 } 569 570 if (type.equals(getJDoubleType())) { 571 return new BasicJDoubleField(this, containingType, name, type, 572 isStatic, offset, staticFieldAddress); 573 } 574 575 if (type.equals(getJFloatType())) { 576 return new BasicJFloatField(this, containingType, name, type, 577 isStatic, offset, staticFieldAddress); 578 } 579 580 if (type.equals(getJIntType())) { 581 return new BasicJIntField(this, containingType, name, type, 582 isStatic, offset, staticFieldAddress); 583 } 584 585 if (type.equals(getJLongType())) { 586 return new BasicJLongField(this, containingType, name, type, 587 isStatic, offset, staticFieldAddress); 588 } 589 590 if (type.equals(getJShortType())) { 591 return new BasicJShortField(this, containingType, name, type, 592 isStatic, offset, staticFieldAddress); 593 } 594 595 // Unknown ("opaque") type. Instantiate ordinary Field. 596 return new BasicField(this, containingType, name, type, 597 isStatic, offset, staticFieldAddress); 598 } 599 600 // For debugging 601 private void dumpMemory(Address addr, int len) { 602 int i = 0; 603 while (i < len) { 604 System.err.print(addr.addOffsetTo(i) + ":"); 605 for (int j = 0; j < 8 && i < len; i++, j++) { 606 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); 607 System.err.print(" 0x"); 608 for (int k = 0; k < 2 - s.length(); k++) { 609 System.err.print("0"); 610 } 611 System.err.print(s); 612 } 613 System.err.println(); 614 } 615 } 616 }