1 /* 2 * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package com.sun.org.apache.bcel.internal.generic; 21 22 import java.util.HashMap; 23 import java.util.Map; 24 25 import com.sun.org.apache.bcel.internal.Const; 26 import com.sun.org.apache.bcel.internal.classfile.Constant; 27 import com.sun.org.apache.bcel.internal.classfile.ConstantCP; 28 import com.sun.org.apache.bcel.internal.classfile.ConstantClass; 29 import com.sun.org.apache.bcel.internal.classfile.ConstantDouble; 30 import com.sun.org.apache.bcel.internal.classfile.ConstantFieldref; 31 import com.sun.org.apache.bcel.internal.classfile.ConstantFloat; 32 import com.sun.org.apache.bcel.internal.classfile.ConstantInteger; 33 import com.sun.org.apache.bcel.internal.classfile.ConstantInterfaceMethodref; 34 import com.sun.org.apache.bcel.internal.classfile.ConstantInvokeDynamic; 35 import com.sun.org.apache.bcel.internal.classfile.ConstantLong; 36 import com.sun.org.apache.bcel.internal.classfile.ConstantMethodref; 37 import com.sun.org.apache.bcel.internal.classfile.ConstantNameAndType; 38 import com.sun.org.apache.bcel.internal.classfile.ConstantPool; 39 import com.sun.org.apache.bcel.internal.classfile.ConstantString; 40 import com.sun.org.apache.bcel.internal.classfile.ConstantUtf8; 41 42 /** 43 * This class is used to build up a constant pool. The user adds 44 * constants via `addXXX' methods, `addString', `addClass', 45 * etc.. These methods return an index into the constant 46 * pool. Finally, `getFinalConstantPool()' returns the constant pool 47 * built up. Intermediate versions of the constant pool can be 48 * obtained with `getConstantPool()'. A constant pool has capacity for 49 * Constants.MAX_SHORT entries. Note that the first (0) is used by the 50 * JVM and that Double and Long constants need two slots. 51 * 52 * @see Constant 53 * @LastModified: Jan 2020 54 */ 55 public class ConstantPoolGen { 56 57 private static final int DEFAULT_BUFFER_SIZE = 256; 58 private int size; 59 private Constant[] constants; 60 private int index = 1; // First entry (0) used by JVM 61 62 private static final String METHODREF_DELIM = ":"; 63 private static final String IMETHODREF_DELIM = "#"; 64 private static final String FIELDREF_DELIM = "&"; 65 private static final String NAT_DELIM = "%"; // Name and Type 66 67 private static class Index { 68 69 final int index; 70 71 Index(final int i)72 Index(final int i) { 73 index = i; 74 } 75 } 76 77 78 /** 79 * Initialize with given array of constants. 80 * 81 * @param cs array of given constants, new ones will be appended 82 */ ConstantPoolGen(final Constant[] cs)83 public ConstantPoolGen(final Constant[] cs) { 84 final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); 85 86 size = Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64); 87 constants = new Constant[size]; 88 89 System.arraycopy(cs, 0, constants, 0, cs.length); 90 if (cs.length > 0) { 91 index = cs.length; 92 } 93 94 95 for (int i = 1; i < index; i++) { 96 final Constant c = constants[i]; 97 if (c instanceof ConstantString) { 98 final ConstantString s = (ConstantString) c; 99 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 100 final String key = u8.getBytes(); 101 if (!string_table.containsKey(key)) { 102 string_table.put(key, new Index(i)); 103 } 104 } else if (c instanceof ConstantClass) { 105 final ConstantClass s = (ConstantClass) c; 106 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 107 final String key = u8.getBytes(); 108 if (!class_table.containsKey(key)) { 109 class_table.put(key, new Index(i)); 110 } 111 } else if (c instanceof ConstantNameAndType) { 112 final ConstantNameAndType n = (ConstantNameAndType) c; 113 final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 114 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 115 116 sb.append(u8.getBytes()); 117 sb.append(NAT_DELIM); 118 sb.append(u8_2.getBytes()); 119 final String key = sb.toString(); 120 sb.delete(0, sb.length()); 121 122 if (!n_a_t_table.containsKey(key)) { 123 n_a_t_table.put(key, new Index(i)); 124 } 125 } else if (c instanceof ConstantUtf8) { 126 final ConstantUtf8 u = (ConstantUtf8) c; 127 final String key = u.getBytes(); 128 if (!utf8_table.containsKey(key)) { 129 utf8_table.put(key, new Index(i)); 130 } 131 } else if (c instanceof ConstantCP) { 132 final ConstantCP m = (ConstantCP) c; 133 String class_name; 134 ConstantUtf8 u8; 135 136 if (c instanceof ConstantInvokeDynamic) { 137 class_name = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex()); 138 // since name can't begin with digit, can use 139 // METHODREF_DELIM with out fear of duplicates. 140 } else { 141 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 142 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 143 class_name = u8.getBytes().replace('/', '.'); 144 } 145 146 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 147 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 148 final String method_name = u8.getBytes(); 149 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 150 final String signature = u8.getBytes(); 151 152 String delim = METHODREF_DELIM; 153 if (c instanceof ConstantInterfaceMethodref) { 154 delim = IMETHODREF_DELIM; 155 } else if (c instanceof ConstantFieldref) { 156 delim = FIELDREF_DELIM; 157 } 158 159 sb.append(class_name); 160 sb.append(delim); 161 sb.append(method_name); 162 sb.append(delim); 163 sb.append(signature); 164 final String key = sb.toString(); 165 sb.delete(0, sb.length()); 166 167 if (!cp_table.containsKey(key)) { 168 cp_table.put(key, new Index(i)); 169 } 170 } else if (c == null) { // entries may be null 171 // nothing to do 172 } else if (c instanceof ConstantInteger) { 173 // nothing to do 174 } else if (c instanceof ConstantLong) { 175 // nothing to do 176 } else if (c instanceof ConstantFloat) { 177 // nothing to do 178 } else if (c instanceof ConstantDouble) { 179 // nothing to do 180 } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodType) { 181 // TODO should this be handled somehow? 182 } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantMethodHandle) { 183 // TODO should this be handled somehow? 184 } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantModule) { 185 // TODO should this be handled somehow? 186 } else if (c instanceof com.sun.org.apache.bcel.internal.classfile.ConstantPackage) { 187 // TODO should this be handled somehow? 188 } else { 189 assert false : "Unexpected constant type: " + c.getClass().getName(); 190 } 191 } 192 } 193 194 195 /** 196 * Initialize with given constant pool. 197 */ ConstantPoolGen(final ConstantPool cp)198 public ConstantPoolGen(final ConstantPool cp) { 199 this(cp.getConstantPool()); 200 } 201 202 203 /** 204 * Create empty constant pool. 205 */ ConstantPoolGen()206 public ConstantPoolGen() { 207 size = DEFAULT_BUFFER_SIZE; 208 constants = new Constant[size]; 209 } 210 211 212 /** Resize internal array of constants. 213 */ adjustSize()214 protected void adjustSize() { 215 if (index + 3 >= size) { 216 final Constant[] cs = constants; 217 size *= 2; 218 constants = new Constant[size]; 219 System.arraycopy(cs, 0, constants, 0, index); 220 } 221 } 222 223 private final Map<String, Index> string_table = new HashMap<>(); 224 225 226 /** 227 * Look for ConstantString in ConstantPool containing String `str'. 228 * 229 * @param str String to search for 230 * @return index on success, -1 otherwise 231 */ lookupString( final String str )232 public int lookupString( final String str ) { 233 final Index index = string_table.get(str); 234 return (index != null) ? index.index : -1; 235 } 236 237 238 /** 239 * Add a new String constant to the ConstantPool, if it is not already in there. 240 * 241 * @param str String to add 242 * @return index of entry 243 */ addString( final String str )244 public int addString( final String str ) { 245 int ret; 246 if ((ret = lookupString(str)) != -1) { 247 return ret; // Already in CP 248 } 249 final int utf8 = addUtf8(str); 250 adjustSize(); 251 final ConstantString s = new ConstantString(utf8); 252 ret = index; 253 constants[index++] = s; 254 if (!string_table.containsKey(str)) { 255 string_table.put(str, new Index(ret)); 256 } 257 return ret; 258 } 259 260 private final Map<String, Index> class_table = new HashMap<>(); 261 262 263 /** 264 * Look for ConstantClass in ConstantPool named `str'. 265 * 266 * @param str String to search for 267 * @return index on success, -1 otherwise 268 */ lookupClass( final String str )269 public int lookupClass( final String str ) { 270 final Index index = class_table.get(str.replace('.', '/')); 271 return (index != null) ? index.index : -1; 272 } 273 274 addClass_( final String clazz )275 private int addClass_( final String clazz ) { 276 int ret; 277 if ((ret = lookupClass(clazz)) != -1) { 278 return ret; // Already in CP 279 } 280 adjustSize(); 281 final ConstantClass c = new ConstantClass(addUtf8(clazz)); 282 ret = index; 283 constants[index++] = c; 284 if (!class_table.containsKey(clazz)) { 285 class_table.put(clazz, new Index(ret)); 286 } 287 return ret; 288 } 289 290 291 /** 292 * Add a new Class reference to the ConstantPool, if it is not already in there. 293 * 294 * @param str Class to add 295 * @return index of entry 296 */ addClass( final String str )297 public int addClass( final String str ) { 298 return addClass_(str.replace('.', '/')); 299 } 300 301 302 /** 303 * Add a new Class reference to the ConstantPool for a given type. 304 * 305 * @param type Class to add 306 * @return index of entry 307 */ addClass( final ObjectType type )308 public int addClass( final ObjectType type ) { 309 return addClass(type.getClassName()); 310 } 311 312 313 /** 314 * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY 315 * instruction, e.g. to the ConstantPool. 316 * 317 * @param type type of array class 318 * @return index of entry 319 */ addArrayClass( final ArrayType type )320 public int addArrayClass( final ArrayType type ) { 321 return addClass_(type.getSignature()); 322 } 323 324 325 /** 326 * Look for ConstantInteger in ConstantPool. 327 * 328 * @param n integer number to look for 329 * @return index on success, -1 otherwise 330 */ lookupInteger( final int n )331 public int lookupInteger( final int n ) { 332 for (int i = 1; i < index; i++) { 333 if (constants[i] instanceof ConstantInteger) { 334 final ConstantInteger c = (ConstantInteger) constants[i]; 335 if (c.getBytes() == n) { 336 return i; 337 } 338 } 339 } 340 return -1; 341 } 342 343 344 /** 345 * Add a new Integer constant to the ConstantPool, if it is not already in there. 346 * 347 * @param n integer number to add 348 * @return index of entry 349 */ addInteger( final int n )350 public int addInteger( final int n ) { 351 int ret; 352 if ((ret = lookupInteger(n)) != -1) { 353 return ret; // Already in CP 354 } 355 adjustSize(); 356 ret = index; 357 constants[index++] = new ConstantInteger(n); 358 return ret; 359 } 360 361 362 /** 363 * Look for ConstantFloat in ConstantPool. 364 * 365 * @param n Float number to look for 366 * @return index on success, -1 otherwise 367 */ lookupFloat( final float n )368 public int lookupFloat( final float n ) { 369 final int bits = Float.floatToIntBits(n); 370 for (int i = 1; i < index; i++) { 371 if (constants[i] instanceof ConstantFloat) { 372 final ConstantFloat c = (ConstantFloat) constants[i]; 373 if (Float.floatToIntBits(c.getBytes()) == bits) { 374 return i; 375 } 376 } 377 } 378 return -1; 379 } 380 381 382 /** 383 * Add a new Float constant to the ConstantPool, if it is not already in there. 384 * 385 * @param n Float number to add 386 * @return index of entry 387 */ addFloat( final float n )388 public int addFloat( final float n ) { 389 int ret; 390 if ((ret = lookupFloat(n)) != -1) { 391 return ret; // Already in CP 392 } 393 adjustSize(); 394 ret = index; 395 constants[index++] = new ConstantFloat(n); 396 return ret; 397 } 398 399 private final Map<String, Index> utf8_table = new HashMap<>(); 400 401 402 /** 403 * Look for ConstantUtf8 in ConstantPool. 404 * 405 * @param n Utf8 string to look for 406 * @return index on success, -1 otherwise 407 */ lookupUtf8( final String n )408 public int lookupUtf8( final String n ) { 409 final Index index = utf8_table.get(n); 410 return (index != null) ? index.index : -1; 411 } 412 413 414 /** 415 * Add a new Utf8 constant to the ConstantPool, if it is not already in there. 416 * 417 * @param n Utf8 string to add 418 * @return index of entry 419 */ addUtf8( final String n )420 public int addUtf8( final String n ) { 421 int ret; 422 if ((ret = lookupUtf8(n)) != -1) { 423 return ret; // Already in CP 424 } 425 adjustSize(); 426 ret = index; 427 constants[index++] = new ConstantUtf8(n); 428 if (!utf8_table.containsKey(n)) { 429 utf8_table.put(n, new Index(ret)); 430 } 431 return ret; 432 } 433 434 435 /** 436 * Look for ConstantLong in ConstantPool. 437 * 438 * @param n Long number to look for 439 * @return index on success, -1 otherwise 440 */ lookupLong( final long n )441 public int lookupLong( final long n ) { 442 for (int i = 1; i < index; i++) { 443 if (constants[i] instanceof ConstantLong) { 444 final ConstantLong c = (ConstantLong) constants[i]; 445 if (c.getBytes() == n) { 446 return i; 447 } 448 } 449 } 450 return -1; 451 } 452 453 454 /** 455 * Add a new long constant to the ConstantPool, if it is not already in there. 456 * 457 * @param n Long number to add 458 * @return index of entry 459 */ addLong( final long n )460 public int addLong( final long n ) { 461 int ret; 462 if ((ret = lookupLong(n)) != -1) { 463 return ret; // Already in CP 464 } 465 adjustSize(); 466 ret = index; 467 constants[index] = new ConstantLong(n); 468 index += 2; // Wastes one entry according to spec 469 return ret; 470 } 471 472 473 /** 474 * Look for ConstantDouble in ConstantPool. 475 * 476 * @param n Double number to look for 477 * @return index on success, -1 otherwise 478 */ lookupDouble( final double n )479 public int lookupDouble( final double n ) { 480 final long bits = Double.doubleToLongBits(n); 481 for (int i = 1; i < index; i++) { 482 if (constants[i] instanceof ConstantDouble) { 483 final ConstantDouble c = (ConstantDouble) constants[i]; 484 if (Double.doubleToLongBits(c.getBytes()) == bits) { 485 return i; 486 } 487 } 488 } 489 return -1; 490 } 491 492 493 /** 494 * Add a new double constant to the ConstantPool, if it is not already in there. 495 * 496 * @param n Double number to add 497 * @return index of entry 498 */ addDouble( final double n )499 public int addDouble( final double n ) { 500 int ret; 501 if ((ret = lookupDouble(n)) != -1) { 502 return ret; // Already in CP 503 } 504 adjustSize(); 505 ret = index; 506 constants[index] = new ConstantDouble(n); 507 index += 2; // Wastes one entry according to spec 508 return ret; 509 } 510 511 private final Map<String, Index> n_a_t_table = new HashMap<>(); 512 513 514 /** 515 * Look for ConstantNameAndType in ConstantPool. 516 * 517 * @param name of variable/method 518 * @param signature of variable/method 519 * @return index on success, -1 otherwise 520 */ lookupNameAndType( final String name, final String signature )521 public int lookupNameAndType( final String name, final String signature ) { 522 final Index _index = n_a_t_table.get(name + NAT_DELIM + signature); 523 return (_index != null) ? _index.index : -1; 524 } 525 526 527 /** 528 * Add a new NameAndType constant to the ConstantPool if it is not already 529 * in there. 530 * 531 * @param name Name string to add 532 * @param signature signature string to add 533 * @return index of entry 534 */ addNameAndType( final String name, final String signature )535 public int addNameAndType( final String name, final String signature ) { 536 int ret; 537 int name_index; 538 int signature_index; 539 if ((ret = lookupNameAndType(name, signature)) != -1) { 540 return ret; // Already in CP 541 } 542 adjustSize(); 543 name_index = addUtf8(name); 544 signature_index = addUtf8(signature); 545 ret = index; 546 constants[index++] = new ConstantNameAndType(name_index, signature_index); 547 final String key = name + NAT_DELIM + signature; 548 if (!n_a_t_table.containsKey(key)) { 549 n_a_t_table.put(key, new Index(ret)); 550 } 551 return ret; 552 } 553 554 private final Map<String, Index> cp_table = new HashMap<>(); 555 556 557 /** 558 * Look for ConstantMethodref in ConstantPool. 559 * 560 * @param class_name Where to find method 561 * @param method_name Guess what 562 * @param signature return and argument types 563 * @return index on success, -1 otherwise 564 */ lookupMethodref( final String class_name, final String method_name, final String signature )565 public int lookupMethodref( final String class_name, final String method_name, final String signature ) { 566 final Index index = cp_table.get(class_name + METHODREF_DELIM + method_name 567 + METHODREF_DELIM + signature); 568 return (index != null) ? index.index : -1; 569 } 570 571 lookupMethodref( final MethodGen method )572 public int lookupMethodref( final MethodGen method ) { 573 return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); 574 } 575 576 577 /** 578 * Add a new Methodref constant to the ConstantPool, if it is not already 579 * in there. 580 * 581 * @param class_name class name string to add 582 * @param method_name method name string to add 583 * @param signature method signature string to add 584 * @return index of entry 585 */ addMethodref( final String class_name, final String method_name, final String signature )586 public int addMethodref( final String class_name, final String method_name, final String signature ) { 587 int ret; 588 int class_index; 589 int name_and_type_index; 590 if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) { 591 return ret; // Already in CP 592 } 593 adjustSize(); 594 name_and_type_index = addNameAndType(method_name, signature); 595 class_index = addClass(class_name); 596 ret = index; 597 constants[index++] = new ConstantMethodref(class_index, name_and_type_index); 598 final String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature; 599 if (!cp_table.containsKey(key)) { 600 cp_table.put(key, new Index(ret)); 601 } 602 return ret; 603 } 604 605 addMethodref( final MethodGen method )606 public int addMethodref( final MethodGen method ) { 607 return addMethodref(method.getClassName(), method.getName(), method.getSignature()); 608 } 609 610 611 /** 612 * Look for ConstantInterfaceMethodref in ConstantPool. 613 * 614 * @param class_name Where to find method 615 * @param method_name Guess what 616 * @param signature return and argument types 617 * @return index on success, -1 otherwise 618 */ lookupInterfaceMethodref( final String class_name, final String method_name, final String signature )619 public int lookupInterfaceMethodref( final String class_name, final String method_name, final String signature ) { 620 final Index index = cp_table.get(class_name + IMETHODREF_DELIM + method_name 621 + IMETHODREF_DELIM + signature); 622 return (index != null) ? index.index : -1; 623 } 624 625 lookupInterfaceMethodref( final MethodGen method )626 public int lookupInterfaceMethodref( final MethodGen method ) { 627 return lookupInterfaceMethodref(method.getClassName(), method.getName(), method 628 .getSignature()); 629 } 630 631 632 /** 633 * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already 634 * in there. 635 * 636 * @param class_name class name string to add 637 * @param method_name method name string to add 638 * @param signature signature string to add 639 * @return index of entry 640 */ addInterfaceMethodref( final String class_name, final String method_name, final String signature )641 public int addInterfaceMethodref( final String class_name, final String method_name, final String signature ) { 642 int ret; 643 int class_index; 644 int name_and_type_index; 645 if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) { 646 return ret; // Already in CP 647 } 648 adjustSize(); 649 class_index = addClass(class_name); 650 name_and_type_index = addNameAndType(method_name, signature); 651 ret = index; 652 constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); 653 final String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature; 654 if (!cp_table.containsKey(key)) { 655 cp_table.put(key, new Index(ret)); 656 } 657 return ret; 658 } 659 660 addInterfaceMethodref( final MethodGen method )661 public int addInterfaceMethodref( final MethodGen method ) { 662 return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 663 } 664 665 666 /** 667 * Look for ConstantFieldref in ConstantPool. 668 * 669 * @param class_name Where to find method 670 * @param field_name Guess what 671 * @param signature return and argument types 672 * @return index on success, -1 otherwise 673 */ lookupFieldref( final String class_name, final String field_name, final String signature )674 public int lookupFieldref( final String class_name, final String field_name, final String signature ) { 675 final Index index = cp_table.get(class_name + FIELDREF_DELIM + field_name 676 + FIELDREF_DELIM + signature); 677 return (index != null) ? index.index : -1; 678 } 679 680 681 /** 682 * Add a new Fieldref constant to the ConstantPool, if it is not already 683 * in there. 684 * 685 * @param class_name class name string to add 686 * @param field_name field name string to add 687 * @param signature signature string to add 688 * @return index of entry 689 */ addFieldref( final String class_name, final String field_name, final String signature )690 public int addFieldref( final String class_name, final String field_name, final String signature ) { 691 int ret; 692 int class_index; 693 int name_and_type_index; 694 if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) { 695 return ret; // Already in CP 696 } 697 adjustSize(); 698 class_index = addClass(class_name); 699 name_and_type_index = addNameAndType(field_name, signature); 700 ret = index; 701 constants[index++] = new ConstantFieldref(class_index, name_and_type_index); 702 final String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature; 703 if (!cp_table.containsKey(key)) { 704 cp_table.put(key, new Index(ret)); 705 } 706 return ret; 707 } 708 709 710 /** 711 * @param i index in constant pool 712 * @return constant pool entry at index i 713 */ getConstant( final int i )714 public Constant getConstant( final int i ) { 715 return constants[i]; 716 } 717 718 719 /** 720 * Use with care! 721 * 722 * @param i index in constant pool 723 * @param c new constant pool entry at index i 724 */ setConstant( final int i, final Constant c )725 public void setConstant( final int i, final Constant c ) { 726 constants[i] = c; 727 } 728 729 730 /** 731 * @return intermediate constant pool 732 */ getConstantPool()733 public ConstantPool getConstantPool() { 734 return new ConstantPool(constants); 735 } 736 737 738 /** 739 * @return current size of constant pool 740 */ getSize()741 public int getSize() { 742 return index; 743 } 744 745 746 /** 747 * @return constant pool with proper length 748 */ getFinalConstantPool()749 public ConstantPool getFinalConstantPool() { 750 final Constant[] cs = new Constant[index]; 751 System.arraycopy(constants, 0, cs, 0, index); 752 return new ConstantPool(cs); 753 } 754 755 756 /** 757 * @return String representation. 758 */ 759 @Override toString()760 public String toString() { 761 final StringBuilder buf = new StringBuilder(); 762 for (int i = 1; i < index; i++) { 763 buf.append(i).append(")").append(constants[i]).append("\n"); 764 } 765 return buf.toString(); 766 } 767 768 769 /** Import constant from another ConstantPool and return new index. 770 */ addConstant( final Constant c, final ConstantPoolGen cp )771 public int addConstant( final Constant c, final ConstantPoolGen cp ) { 772 final Constant[] constants = cp.getConstantPool().getConstantPool(); 773 switch (c.getTag()) { 774 case Const.CONSTANT_String: { 775 final ConstantString s = (ConstantString) c; 776 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 777 return addString(u8.getBytes()); 778 } 779 case Const.CONSTANT_Class: { 780 final ConstantClass s = (ConstantClass) c; 781 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 782 return addClass(u8.getBytes()); 783 } 784 case Const.CONSTANT_NameAndType: { 785 final ConstantNameAndType n = (ConstantNameAndType) c; 786 final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 787 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 788 return addNameAndType(u8.getBytes(), u8_2.getBytes()); 789 } 790 case Const.CONSTANT_Utf8: 791 return addUtf8(((ConstantUtf8) c).getBytes()); 792 case Const.CONSTANT_Double: 793 return addDouble(((ConstantDouble) c).getBytes()); 794 case Const.CONSTANT_Float: 795 return addFloat(((ConstantFloat) c).getBytes()); 796 case Const.CONSTANT_Long: 797 return addLong(((ConstantLong) c).getBytes()); 798 case Const.CONSTANT_Integer: 799 return addInteger(((ConstantInteger) c).getBytes()); 800 case Const.CONSTANT_InterfaceMethodref: 801 case Const.CONSTANT_Methodref: 802 case Const.CONSTANT_Fieldref: { 803 final ConstantCP m = (ConstantCP) c; 804 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 805 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 806 ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 807 final String class_name = u8.getBytes().replace('/', '.'); 808 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 809 final String name = u8.getBytes(); 810 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 811 final String signature = u8.getBytes(); 812 switch (c.getTag()) { 813 case Const.CONSTANT_InterfaceMethodref: 814 return addInterfaceMethodref(class_name, name, signature); 815 case Const.CONSTANT_Methodref: 816 return addMethodref(class_name, name, signature); 817 case Const.CONSTANT_Fieldref: 818 return addFieldref(class_name, name, signature); 819 default: // Never reached 820 throw new RuntimeException("Unknown constant type " + c); 821 } 822 } 823 default: // Never reached 824 throw new RuntimeException("Unknown constant type " + c); 825 } 826 } 827 } 828