1 /* 2 * Copyright (c) 2000, 2017, 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.oops; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.runtime.*; 31 import sun.jvm.hotspot.types.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 // A ConstantPool is an oop containing class constants 35 // as described in the class file 36 37 public class ConstantPool extends Metadata implements ClassConstants { 38 public class CPSlot { 39 private Address ptr; 40 41 CPSlot(Address ptr) { 42 this.ptr = ptr; 43 } 44 CPSlot(Symbol sym) { 45 this.ptr = sym.getAddress().orWithMask(1); 46 } 47 48 public boolean isResolved() { 49 return (ptr.minus(null) & 1) == 0; 50 } 51 public boolean isUnresolved() { 52 return (ptr.minus(null) & 1) == 1; 53 } 54 55 public Symbol getSymbol() { 56 if (!isUnresolved()) throw new InternalError("not a symbol"); 57 return Symbol.create(ptr.xorWithMask(1)); 58 } 59 public Klass getKlass() { 60 if (!isResolved()) throw new InternalError("not klass"); 61 return (Klass)Metadata.instantiateWrapperFor(ptr); 62 } 63 } 64 65 // Used for debugging this code 66 private static final boolean DEBUG = false; 67 68 protected void debugMessage(String message) { 69 System.out.println(message); 70 } 71 72 static { 73 VM.registerVMInitializedObserver(new Observer() { 74 public void update(Observable o, Object data) { 75 initialize(VM.getVM().getTypeDataBase()); 76 } 77 }); 78 } 79 80 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 81 Type type = db.lookupType("ConstantPool"); 82 tags = type.getAddressField("_tags"); 83 operands = type.getAddressField("_operands"); 84 cache = type.getAddressField("_cache"); 85 poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0); 86 length = new CIntField(type.getCIntegerField("_length"), 0); 87 headerSize = type.getSize(); 88 elementSize = 0; 89 // fetch constants: 90 INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); 91 INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); 92 INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); 93 } 94 95 public ConstantPool(Address addr) { 96 super(addr); 97 } 98 99 public boolean isConstantPool() { return true; } 100 101 private static AddressField tags; 102 private static AddressField operands; 103 private static AddressField cache; 104 private static MetadataField poolHolder; 105 private static CIntField length; // number of elements in oop 106 107 private static long headerSize; 108 private static long elementSize; 109 110 private static int INDY_BSM_OFFSET; 111 private static int INDY_ARGC_OFFSET; 112 private static int INDY_ARGV_OFFSET; 113 114 public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); } 115 public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); } 116 public ConstantPoolCache getCache() { 117 Address addr = cache.getValue(getAddress()); 118 return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr); 119 } 120 public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); } 121 public int getLength() { return (int)length.getValue(getAddress()); } 122 public Oop getResolvedReferences() { 123 return getCache().getResolvedReferences(); 124 } 125 126 public U2Array referenceMap() { 127 return getCache().referenceMap(); 128 } 129 130 public int objectToCPIndex(int index) { 131 return referenceMap().at(index); 132 } 133 134 private long getElementSize() { 135 if (elementSize !=0 ) { 136 return elementSize; 137 } else { 138 elementSize = VM.getVM().getOopSize(); 139 } 140 return elementSize; 141 } 142 143 private long indexOffset(long index) { 144 if (Assert.ASSERTS_ENABLED) { 145 Assert.that(index >= 0 && index < getLength(), "invalid cp index " + index + " " + getLength()); 146 } 147 return (index * getElementSize()) + headerSize; 148 } 149 150 public ConstantTag getTagAt(long index) { 151 return new ConstantTag((byte)getTags().at((int) index)); 152 } 153 154 public CPSlot getSlotAt(long index) { 155 return new CPSlot(getAddressAtRaw(index)); 156 } 157 158 public Address getAddressAtRaw(long index) { 159 return getAddress().getAddressAt(indexOffset(index)); 160 } 161 162 public Symbol getSymbolAt(long index) { 163 return Symbol.create(getAddressAtRaw(index)); 164 } 165 166 public int getIntAt(long index){ 167 return getAddress().getJIntAt(indexOffset(index)); 168 } 169 170 public float getFloatAt(long index){ 171 return getAddress().getJFloatAt(indexOffset(index)); 172 } 173 174 public long getLongAt(long index) { 175 int oneHalf = getAddress().getJIntAt(indexOffset(index + 1)); 176 int otherHalf = getAddress().getJIntAt(indexOffset(index)); 177 // buildLongFromIntsPD accepts higher address value, lower address value 178 // in that order. 179 return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); 180 } 181 182 public double getDoubleAt(long index) { 183 return Double.longBitsToDouble(getLongAt(index)); 184 } 185 186 public int getFieldOrMethodAt(int which) { 187 if (DEBUG) { 188 System.err.print("ConstantPool.getFieldOrMethodAt(" + which + "): new index = "); 189 } 190 int i = -1; 191 ConstantPoolCache cache = getCache(); 192 if (cache == null) { 193 i = which; 194 } else { 195 // change byte-ordering and go via cache 196 i = cache.getEntryAt(0xFFFF & which).getConstantPoolIndex(); 197 } 198 if (Assert.ASSERTS_ENABLED) { 199 Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); 200 } 201 if (DEBUG) { 202 System.err.println(i); 203 } 204 int res = getIntAt(i); 205 if (DEBUG) { 206 System.err.println("ConstantPool.getFieldOrMethodAt(" + i + "): result = " + res); 207 } 208 return res; 209 } 210 211 public int[] getNameAndTypeAt(int which) { 212 if (Assert.ASSERTS_ENABLED) { 213 Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool: " + which + " " + getTagAt(which)); 214 } 215 int i = getIntAt(which); 216 if (DEBUG) { 217 System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i); 218 } 219 return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) }; 220 } 221 222 public Symbol getNameRefAt(int which) { 223 return implGetNameRefAt(which, false); 224 } 225 226 public Symbol uncachedGetNameRefAt(int which) { 227 return implGetNameRefAt(which, true); 228 } 229 230 private Symbol implGetNameRefAt(int which, boolean uncached) { 231 int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); 232 return getSymbolAt(signatureIndex); 233 } 234 235 public Symbol getSignatureRefAt(int which) { 236 return implGetSignatureRefAt(which, false); 237 } 238 239 public Symbol uncachedGetSignatureRefAt(int which) { 240 return implGetSignatureRefAt(which, true); 241 } 242 243 private Symbol implGetSignatureRefAt(int which, boolean uncached) { 244 int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); 245 return getSymbolAt(signatureIndex); 246 } 247 248 public static boolean isInvokedynamicIndex(int i) { return (i < 0); } 249 250 public static int decodeInvokedynamicIndex(int i) { Assert.that(isInvokedynamicIndex(i), ""); return ~i; } 251 252 // The invokedynamic points at the object index. The object map points at 253 // the cpCache index and the cpCache entry points at the original constant 254 // pool index. 255 public int invokedynamicCPCacheIndex(int index) { 256 Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index"); 257 int rawIndex = decodeInvokedynamicIndex(index); 258 return referenceMap().at(rawIndex); 259 } 260 261 ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) { 262 // decode index that invokedynamic points to. 263 int cpCacheIndex = invokedynamicCPCacheIndex(index); 264 return getCache().getEntryAt(cpCacheIndex); 265 } 266 267 private int implNameAndTypeRefIndexAt(int which, boolean uncached) { 268 int i = which; 269 if (!uncached && getCache() != null) { 270 if (isInvokedynamicIndex(which)) { 271 // Invokedynamic index is index into resolved_references 272 int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex(); 273 poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex); 274 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 275 return poolIndex; 276 } 277 // change byte-ordering and go via cache 278 i = remapInstructionOperandFromCache(which); 279 } else { 280 if (getTagAt(which).isInvokeDynamic()) { 281 int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which); 282 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 283 return poolIndex; 284 } 285 } 286 // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); 287 // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); 288 int refIndex = getIntAt(i); 289 return extractHighShortFromInt(refIndex); 290 } 291 292 private int remapInstructionOperandFromCache(int operand) { 293 int cpc_index = operand; 294 // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG); 295 // assert((int)(u2)cpc_index == cpc_index, "clean u2"); 296 int member_index = getCache().getEntryAt(cpc_index).getConstantPoolIndex(); 297 return member_index; 298 } 299 300 public int invokeDynamicNameAndTypeRefIndexAt(int which) { 301 // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); 302 return extractHighShortFromInt(getIntAt(which)); 303 } 304 305 // returns null, if not resolved. 306 public Klass getKlassAt(int which) { 307 if( ! getTagAt(which).isKlass()) return null; 308 return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); 309 } 310 311 public Symbol getKlassNameAt(int which) { 312 CPSlot entry = getSlotAt(which); 313 if (entry.isResolved()) { 314 return entry.getKlass().getName(); 315 } else { 316 return entry.getSymbol(); 317 } 318 } 319 320 public Symbol getUnresolvedStringAt(int which) { 321 return getSlotAt(which).getSymbol(); 322 } 323 324 // returns null, if not resolved. 325 public InstanceKlass getFieldOrMethodKlassRefAt(int which) { 326 int refIndex = getFieldOrMethodAt(which); 327 int klassIndex = extractLowShortFromInt(refIndex); 328 return (InstanceKlass) getKlassAt(klassIndex); 329 } 330 331 // returns null, if not resolved. 332 public Method getMethodRefAt(int which) { 333 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 334 if (klass == null) return null; 335 Symbol name = getNameRefAt(which); 336 Symbol sig = getSignatureRefAt(which); 337 return klass.findMethod(name, sig); 338 } 339 340 // returns null, if not resolved. 341 public Field getFieldRefAt(int which) { 342 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 343 if (klass == null) return null; 344 Symbol name = getNameRefAt(which); 345 Symbol sig = getSignatureRefAt(which); 346 return klass.findField(name, sig); 347 } 348 349 public int getNameAndTypeRefIndexAt(int index) { 350 return implNameAndTypeRefIndexAt(index, false); 351 } 352 353 /** Lookup for entries consisting of (name_index, signature_index) */ 354 public int getNameRefIndexAt(int index) { 355 int[] refIndex = getNameAndTypeAt(index); 356 if (DEBUG) { 357 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 358 } 359 int i = refIndex[0]; 360 if (DEBUG) { 361 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i); 362 } 363 return i; 364 } 365 366 /** Lookup for entries consisting of (name_index, signature_index) */ 367 public int getSignatureRefIndexAt(int index) { 368 int[] refIndex = getNameAndTypeAt(index); 369 if (DEBUG) { 370 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 371 } 372 int i = refIndex[1]; 373 if (DEBUG) { 374 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i); 375 } 376 return i; 377 } 378 379 /** Lookup for MethodHandle entries. */ 380 public int getMethodHandleIndexAt(int i) { 381 if (Assert.ASSERTS_ENABLED) { 382 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 383 } 384 int res = extractHighShortFromInt(getIntAt(i)); 385 if (DEBUG) { 386 System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res); 387 } 388 return res; 389 } 390 391 /** Lookup for MethodHandle entries. */ 392 public int getMethodHandleRefKindAt(int i) { 393 if (Assert.ASSERTS_ENABLED) { 394 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 395 } 396 int res = extractLowShortFromInt(getIntAt(i)); 397 if (DEBUG) { 398 System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res); 399 } 400 return res; 401 } 402 403 /** Lookup for MethodType entries. */ 404 public int getMethodTypeIndexAt(int i) { 405 if (Assert.ASSERTS_ENABLED) { 406 Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool"); 407 } 408 int res = getIntAt(i); 409 if (DEBUG) { 410 System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res); 411 } 412 return res; 413 } 414 415 /** Lookup for multi-operand (InvokeDynamic) entries. */ 416 public short[] getBootstrapSpecifierAt(int i) { 417 if (Assert.ASSERTS_ENABLED) { 418 Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); 419 } 420 int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); 421 U2Array operands = getOperands(); 422 if (operands == null) return null; // safety first 423 int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0), 424 operands.at(bsmSpec * 2 + 1)); 425 int argv = basePos + INDY_ARGV_OFFSET; 426 int argc = operands.at(basePos + INDY_ARGC_OFFSET); 427 int endPos = argv + argc; 428 short[] values = new short[endPos - basePos]; 429 for (int j = 0; j < values.length; j++) { 430 values[j] = operands.at(basePos+j); 431 } 432 return values; 433 } 434 435 final private static String[] nameForTag = new String[] { 436 }; 437 438 private String nameForTag(int tag) { 439 switch (tag) { 440 case JVM_CONSTANT_Utf8: return "JVM_CONSTANT_Utf8"; 441 case JVM_CONSTANT_Unicode: return "JVM_CONSTANT_Unicode"; 442 case JVM_CONSTANT_Integer: return "JVM_CONSTANT_Integer"; 443 case JVM_CONSTANT_Float: return "JVM_CONSTANT_Float"; 444 case JVM_CONSTANT_Long: return "JVM_CONSTANT_Long"; 445 case JVM_CONSTANT_Double: return "JVM_CONSTANT_Double"; 446 case JVM_CONSTANT_Class: return "JVM_CONSTANT_Class"; 447 case JVM_CONSTANT_String: return "JVM_CONSTANT_String"; 448 case JVM_CONSTANT_Fieldref: return "JVM_CONSTANT_Fieldref"; 449 case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref"; 450 case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref"; 451 case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType"; 452 case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; 453 case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; 454 case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; 455 case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; 456 case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; 457 case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; 458 case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; 459 case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; 460 case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; 461 case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; 462 } 463 throw new InternalError("Unknown tag: " + tag); 464 } 465 466 public void iterateFields(MetadataVisitor visitor) { 467 super.iterateFields(visitor); 468 visitor.doMetadata(poolHolder, true); 469 470 final int length = (int) getLength(); 471 // zero'th pool entry is always invalid. ignore it. 472 for (int index = 1; index < length; index++) { 473 int ctag = (int) getTags().at((int) index); 474 switch (ctag) { 475 case JVM_CONSTANT_ClassIndex: 476 case JVM_CONSTANT_StringIndex: 477 case JVM_CONSTANT_Integer: 478 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 479 break; 480 481 case JVM_CONSTANT_Float: 482 visitor.doFloat(new FloatField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 483 break; 484 485 case JVM_CONSTANT_Long: 486 visitor.doLong(new LongField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 487 // long entries occupy two slots 488 index++; 489 break; 490 491 case JVM_CONSTANT_Double: 492 visitor.doDouble(new DoubleField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 493 // double entries occupy two slots 494 index++; 495 break; 496 497 case JVM_CONSTANT_UnresolvedClassInError: 498 case JVM_CONSTANT_UnresolvedClass: 499 case JVM_CONSTANT_Class: 500 case JVM_CONSTANT_Utf8: 501 visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 502 break; 503 504 case JVM_CONSTANT_Fieldref: 505 case JVM_CONSTANT_Methodref: 506 case JVM_CONSTANT_InterfaceMethodref: 507 case JVM_CONSTANT_NameAndType: 508 case JVM_CONSTANT_MethodHandle: 509 case JVM_CONSTANT_MethodType: 510 case JVM_CONSTANT_InvokeDynamic: 511 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 512 break; 513 } 514 } 515 } 516 517 public void writeBytes(OutputStream os) throws IOException { 518 // Map between any modified UTF-8 and it's constant pool index. 519 Map utf8ToIndex = new HashMap(); 520 DataOutputStream dos = new DataOutputStream(os); 521 U1Array tags = getTags(); 522 int len = (int)getLength(); 523 int ci = 0; // constant pool index 524 525 // collect all modified UTF-8 Strings from Constant Pool 526 527 for (ci = 1; ci < len; ci++) { 528 int cpConstType = tags.at(ci); 529 if(cpConstType == JVM_CONSTANT_Utf8) { 530 Symbol sym = getSymbolAt(ci); 531 utf8ToIndex.put(sym.asString(), new Short((short) ci)); 532 } 533 else if(cpConstType == JVM_CONSTANT_Long || 534 cpConstType == JVM_CONSTANT_Double) { 535 ci++; 536 } 537 } 538 539 540 for(ci = 1; ci < len; ci++) { 541 int cpConstType = tags.at(ci); 542 // write cp_info 543 // write constant type 544 switch(cpConstType) { 545 case JVM_CONSTANT_Utf8: { 546 dos.writeByte(cpConstType); 547 Symbol sym = getSymbolAt(ci); 548 dos.writeShort((short)sym.getLength()); 549 dos.write(sym.asByteArray()); 550 if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString()); 551 break; 552 } 553 554 case JVM_CONSTANT_Unicode: 555 throw new IllegalArgumentException("Unicode constant!"); 556 557 case JVM_CONSTANT_Integer: 558 dos.writeByte(cpConstType); 559 dos.writeInt(getIntAt(ci)); 560 if (DEBUG) debugMessage("CP[" + ci + "] = int " + getIntAt(ci)); 561 break; 562 563 case JVM_CONSTANT_Float: 564 dos.writeByte(cpConstType); 565 dos.writeFloat(getFloatAt(ci)); 566 if (DEBUG) debugMessage("CP[" + ci + "] = float " + getFloatAt(ci)); 567 break; 568 569 case JVM_CONSTANT_Long: { 570 dos.writeByte(cpConstType); 571 long l = getLongAt(ci); 572 // long entries occupy two pool entries 573 ci++; 574 dos.writeLong(l); 575 break; 576 } 577 578 case JVM_CONSTANT_Double: 579 dos.writeByte(cpConstType); 580 dos.writeDouble(getDoubleAt(ci)); 581 // double entries occupy two pool entries 582 ci++; 583 break; 584 585 case JVM_CONSTANT_Class: { 586 dos.writeByte(cpConstType); 587 // Klass already resolved. ConstantPool constains Klass*. 588 Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci)); 589 String klassName = refKls.getName().asString(); 590 Short s = (Short) utf8ToIndex.get(klassName); 591 dos.writeShort(s.shortValue()); 592 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 593 break; 594 } 595 596 // case JVM_CONSTANT_ClassIndex: 597 case JVM_CONSTANT_UnresolvedClassInError: 598 case JVM_CONSTANT_UnresolvedClass: { 599 dos.writeByte(JVM_CONSTANT_Class); 600 String klassName = getSymbolAt(ci).asString(); 601 Short s = (Short) utf8ToIndex.get(klassName); 602 dos.writeShort(s.shortValue()); 603 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 604 break; 605 } 606 607 case JVM_CONSTANT_String: { 608 dos.writeByte(cpConstType); 609 String str = getUnresolvedStringAt(ci).asString(); 610 Short s = (Short) utf8ToIndex.get(str); 611 dos.writeShort(s.shortValue()); 612 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); 613 break; 614 } 615 616 // all external, internal method/field references 617 case JVM_CONSTANT_Fieldref: 618 case JVM_CONSTANT_Methodref: 619 case JVM_CONSTANT_InterfaceMethodref: { 620 dos.writeByte(cpConstType); 621 int value = getIntAt(ci); 622 short klassIndex = (short) extractLowShortFromInt(value); 623 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 624 dos.writeShort(klassIndex); 625 dos.writeShort(nameAndTypeIndex); 626 if (DEBUG) debugMessage("CP[" + ci + "] = ref klass = " + 627 klassIndex + ", N&T = " + nameAndTypeIndex); 628 break; 629 } 630 631 case JVM_CONSTANT_NameAndType: { 632 dos.writeByte(cpConstType); 633 int value = getIntAt(ci); 634 short nameIndex = (short) extractLowShortFromInt(value); 635 short signatureIndex = (short) extractHighShortFromInt(value); 636 dos.writeShort(nameIndex); 637 dos.writeShort(signatureIndex); 638 if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex 639 + ", type = " + signatureIndex); 640 break; 641 } 642 643 case JVM_CONSTANT_MethodHandle: { 644 dos.writeByte(cpConstType); 645 int value = getIntAt(ci); 646 byte refKind = (byte) extractLowShortFromInt(value); 647 short memberIndex = (short) extractHighShortFromInt(value); 648 dos.writeByte(refKind); 649 dos.writeShort(memberIndex); 650 if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " + 651 refKind + ", mem = " + memberIndex); 652 break; 653 } 654 655 case JVM_CONSTANT_MethodType: { 656 dos.writeByte(cpConstType); 657 int value = getIntAt(ci); 658 short refIndex = (short) value; 659 dos.writeShort(refIndex); 660 if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); 661 break; 662 } 663 664 case JVM_CONSTANT_InvokeDynamic: { 665 dos.writeByte(cpConstType); 666 int value = getIntAt(ci); 667 short bsmIndex = (short) extractLowShortFromInt(value); 668 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 669 dos.writeShort(bsmIndex); 670 dos.writeShort(nameAndTypeIndex); 671 if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " + 672 bsmIndex + ", N&T = " + nameAndTypeIndex); 673 break; 674 } 675 676 default: 677 throw new InternalError("Unknown tag: " + cpConstType); 678 } // switch 679 } 680 dos.flush(); 681 return; 682 } 683 684 public void printValueOn(PrintStream tty) { 685 tty.print("ConstantPool for " + getPoolHolder().getName().asString()); 686 } 687 688 public long getSize() { 689 return alignSize(headerSize + getLength()); 690 } 691 692 //---------------------------------------------------------------------- 693 // Internals only below this point 694 // 695 696 private static int extractHighShortFromInt(int val) { 697 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 698 return (val >> 16) & 0xFFFF; 699 } 700 701 private static int extractLowShortFromInt(int val) { 702 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 703 return val & 0xFFFF; 704 } 705 }