1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm; 60 61 import java.lang.reflect.Constructor; 62 import java.lang.reflect.Method; 63 64 /** 65 * A Java field or method type. This class can be used to make it easier to 66 * manipulate type and method descriptors. 67 * 68 * @author Eric Bruneton 69 * @author Chris Nokleberg 70 */ 71 public class Type { 72 73 /** 74 * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. 75 */ 76 public static final int VOID = 0; 77 78 /** 79 * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. 80 */ 81 public static final int BOOLEAN = 1; 82 83 /** 84 * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. 85 */ 86 public static final int CHAR = 2; 87 88 /** 89 * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. 90 */ 91 public static final int BYTE = 3; 92 93 /** 94 * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. 95 */ 96 public static final int SHORT = 4; 97 98 /** 99 * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. 100 */ 101 public static final int INT = 5; 102 103 /** 104 * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. 105 */ 106 public static final int FLOAT = 6; 107 108 /** 109 * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. 110 */ 111 public static final int LONG = 7; 112 113 /** 114 * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. 115 */ 116 public static final int DOUBLE = 8; 117 118 /** 119 * The sort of array reference types. See {@link #getSort getSort}. 120 */ 121 public static final int ARRAY = 9; 122 123 /** 124 * The sort of object reference types. See {@link #getSort getSort}. 125 */ 126 public static final int OBJECT = 10; 127 128 /** 129 * The sort of method types. See {@link #getSort getSort}. 130 */ 131 public static final int METHOD = 11; 132 133 /** 134 * The <tt>void</tt> type. 135 */ 136 public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) 137 | (5 << 16) | (0 << 8) | 0, 1); 138 139 /** 140 * The <tt>boolean</tt> type. 141 */ 142 public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) 143 | (0 << 16) | (5 << 8) | 1, 1); 144 145 /** 146 * The <tt>char</tt> type. 147 */ 148 public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) 149 | (0 << 16) | (6 << 8) | 1, 1); 150 151 /** 152 * The <tt>byte</tt> type. 153 */ 154 public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) 155 | (0 << 16) | (5 << 8) | 1, 1); 156 157 /** 158 * The <tt>short</tt> type. 159 */ 160 public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) 161 | (0 << 16) | (7 << 8) | 1, 1); 162 163 /** 164 * The <tt>int</tt> type. 165 */ 166 public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) 167 | (0 << 16) | (0 << 8) | 1, 1); 168 169 /** 170 * The <tt>float</tt> type. 171 */ 172 public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) 173 | (2 << 16) | (2 << 8) | 1, 1); 174 175 /** 176 * The <tt>long</tt> type. 177 */ 178 public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) 179 | (1 << 16) | (1 << 8) | 2, 1); 180 181 /** 182 * The <tt>double</tt> type. 183 */ 184 public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) 185 | (3 << 16) | (3 << 8) | 2, 1); 186 187 // ------------------------------------------------------------------------ 188 // Fields 189 // ------------------------------------------------------------------------ 190 191 /** 192 * The sort of this Java type. 193 */ 194 private final int sort; 195 196 /** 197 * A buffer containing the internal name of this Java type. This field is 198 * only used for reference types. 199 */ 200 private final char[] buf; 201 202 /** 203 * The offset of the internal name of this Java type in {@link #buf buf} or, 204 * for primitive types, the size, descriptor and getOpcode offsets for this 205 * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset 206 * for IALOAD or IASTORE, byte 3 the offset for all other instructions). 207 */ 208 private final int off; 209 210 /** 211 * The length of the internal name of this Java type. 212 */ 213 private final int len; 214 215 // ------------------------------------------------------------------------ 216 // Constructors 217 // ------------------------------------------------------------------------ 218 219 /** 220 * Constructs a reference type. 221 * 222 * @param sort 223 * the sort of the reference type to be constructed. 224 * @param buf 225 * a buffer containing the descriptor of the previous type. 226 * @param off 227 * the offset of this descriptor in the previous buffer. 228 * @param len 229 * the length of this descriptor. 230 */ 231 private Type(final int sort, final char[] buf, final int off, final int len) { 232 this.sort = sort; 233 this.buf = buf; 234 this.off = off; 235 this.len = len; 236 } 237 238 /** 239 * Returns the Java type corresponding to the given type descriptor. 240 * 241 * @param typeDescriptor 242 * a field or method type descriptor. 243 * @return the Java type corresponding to the given type descriptor. 244 */ 245 public static Type getType(final String typeDescriptor) { 246 return getType(typeDescriptor.toCharArray(), 0); 247 } 248 249 /** 250 * Returns the Java type corresponding to the given internal name. 251 * 252 * @param internalName 253 * an internal name. 254 * @return the Java type corresponding to the given internal name. 255 */ 256 public static Type getObjectType(final String internalName) { 257 char[] buf = internalName.toCharArray(); 258 return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); 259 } 260 261 /** 262 * Returns the Java type corresponding to the given method descriptor. 263 * Equivalent to <code>Type.getType(methodDescriptor)</code>. 264 * 265 * @param methodDescriptor 266 * a method descriptor. 267 * @return the Java type corresponding to the given method descriptor. 268 */ 269 public static Type getMethodType(final String methodDescriptor) { 270 return getType(methodDescriptor.toCharArray(), 0); 271 } 272 273 /** 274 * Returns the Java method type corresponding to the given argument and 275 * return types. 276 * 277 * @param returnType 278 * the return type of the method. 279 * @param argumentTypes 280 * the argument types of the method. 281 * @return the Java type corresponding to the given argument and return 282 * types. 283 */ 284 public static Type getMethodType(final Type returnType, 285 final Type... argumentTypes) { 286 return getType(getMethodDescriptor(returnType, argumentTypes)); 287 } 288 289 /** 290 * Returns the Java type corresponding to the given class. 291 * 292 * @param c 293 * a class. 294 * @return the Java type corresponding to the given class. 295 */ 296 public static Type getType(final Class<?> c) { 297 if (c.isPrimitive()) { 298 if (c == Integer.TYPE) { 299 return INT_TYPE; 300 } else if (c == Void.TYPE) { 301 return VOID_TYPE; 302 } else if (c == Boolean.TYPE) { 303 return BOOLEAN_TYPE; 304 } else if (c == Byte.TYPE) { 305 return BYTE_TYPE; 306 } else if (c == Character.TYPE) { 307 return CHAR_TYPE; 308 } else if (c == Short.TYPE) { 309 return SHORT_TYPE; 310 } else if (c == Double.TYPE) { 311 return DOUBLE_TYPE; 312 } else if (c == Float.TYPE) { 313 return FLOAT_TYPE; 314 } else /* if (c == Long.TYPE) */{ 315 return LONG_TYPE; 316 } 317 } else { 318 return getType(getDescriptor(c)); 319 } 320 } 321 322 /** 323 * Returns the Java method type corresponding to the given constructor. 324 * 325 * @param c 326 * a {@link Constructor Constructor} object. 327 * @return the Java method type corresponding to the given constructor. 328 */ 329 public static Type getType(final Constructor<?> c) { 330 return getType(getConstructorDescriptor(c)); 331 } 332 333 /** 334 * Returns the Java method type corresponding to the given method. 335 * 336 * @param m 337 * a {@link Method Method} object. 338 * @return the Java method type corresponding to the given method. 339 */ 340 public static Type getType(final Method m) { 341 return getType(getMethodDescriptor(m)); 342 } 343 344 /** 345 * Returns the Java types corresponding to the argument types of the given 346 * method descriptor. 347 * 348 * @param methodDescriptor 349 * a method descriptor. 350 * @return the Java types corresponding to the argument types of the given 351 * method descriptor. 352 */ 353 public static Type[] getArgumentTypes(final String methodDescriptor) { 354 char[] buf = methodDescriptor.toCharArray(); 355 int off = 1; 356 int size = 0; 357 while (true) { 358 char car = buf[off++]; 359 if (car == ')') { 360 break; 361 } else if (car == 'L') { 362 while (buf[off++] != ';') { 363 } 364 ++size; 365 } else if (car != '[') { 366 ++size; 367 } 368 } 369 Type[] args = new Type[size]; 370 off = 1; 371 size = 0; 372 while (buf[off] != ')') { 373 args[size] = getType(buf, off); 374 off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); 375 size += 1; 376 } 377 return args; 378 } 379 380 /** 381 * Returns the Java types corresponding to the argument types of the given 382 * method. 383 * 384 * @param method 385 * a method. 386 * @return the Java types corresponding to the argument types of the given 387 * method. 388 */ 389 public static Type[] getArgumentTypes(final Method method) { 390 Class<?>[] classes = method.getParameterTypes(); 391 Type[] types = new Type[classes.length]; 392 for (int i = classes.length - 1; i >= 0; --i) { 393 types[i] = getType(classes[i]); 394 } 395 return types; 396 } 397 398 /** 399 * Returns the Java type corresponding to the return type of the given 400 * method descriptor. 401 * 402 * @param methodDescriptor 403 * a method descriptor. 404 * @return the Java type corresponding to the return type of the given 405 * method descriptor. 406 */ 407 public static Type getReturnType(final String methodDescriptor) { 408 char[] buf = methodDescriptor.toCharArray(); 409 return getType(buf, methodDescriptor.indexOf(')') + 1); 410 } 411 412 /** 413 * Returns the Java type corresponding to the return type of the given 414 * method. 415 * 416 * @param method 417 * a method. 418 * @return the Java type corresponding to the return type of the given 419 * method. 420 */ 421 public static Type getReturnType(final Method method) { 422 return getType(method.getReturnType()); 423 } 424 425 /** 426 * Computes the size of the arguments and of the return value of a method. 427 * 428 * @param desc 429 * the descriptor of a method. 430 * @return the size of the arguments of the method (plus one for the 431 * implicit this argument), argSize, and the size of its return 432 * value, retSize, packed into a single int i = 433 * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to 434 * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). 435 */ 436 public static int getArgumentsAndReturnSizes(final String desc) { 437 int n = 1; 438 int c = 1; 439 while (true) { 440 char car = desc.charAt(c++); 441 if (car == ')') { 442 car = desc.charAt(c); 443 return n << 2 444 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 445 } else if (car == 'L') { 446 while (desc.charAt(c++) != ';') { 447 } 448 n += 1; 449 } else if (car == '[') { 450 while ((car = desc.charAt(c)) == '[') { 451 ++c; 452 } 453 if (car == 'D' || car == 'J') { 454 n -= 1; 455 } 456 } else if (car == 'D' || car == 'J') { 457 n += 2; 458 } else { 459 n += 1; 460 } 461 } 462 } 463 464 /** 465 * Returns the Java type corresponding to the given type descriptor. For 466 * method descriptors, buf is supposed to contain nothing more than the 467 * descriptor itself. 468 * 469 * @param buf 470 * a buffer containing a type descriptor. 471 * @param off 472 * the offset of this descriptor in the previous buffer. 473 * @return the Java type corresponding to the given type descriptor. 474 */ 475 private static Type getType(final char[] buf, final int off) { 476 int len; 477 switch (buf[off]) { 478 case 'V': 479 return VOID_TYPE; 480 case 'Z': 481 return BOOLEAN_TYPE; 482 case 'C': 483 return CHAR_TYPE; 484 case 'B': 485 return BYTE_TYPE; 486 case 'S': 487 return SHORT_TYPE; 488 case 'I': 489 return INT_TYPE; 490 case 'F': 491 return FLOAT_TYPE; 492 case 'J': 493 return LONG_TYPE; 494 case 'D': 495 return DOUBLE_TYPE; 496 case '[': 497 len = 1; 498 while (buf[off + len] == '[') { 499 ++len; 500 } 501 if (buf[off + len] == 'L') { 502 ++len; 503 while (buf[off + len] != ';') { 504 ++len; 505 } 506 } 507 return new Type(ARRAY, buf, off, len + 1); 508 case 'L': 509 len = 1; 510 while (buf[off + len] != ';') { 511 ++len; 512 } 513 return new Type(OBJECT, buf, off + 1, len - 1); 514 // case '(': 515 default: 516 return new Type(METHOD, buf, off, buf.length - off); 517 } 518 } 519 520 // ------------------------------------------------------------------------ 521 // Accessors 522 // ------------------------------------------------------------------------ 523 524 /** 525 * Returns the sort of this Java type. 526 * 527 * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, 528 * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, 529 * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, 530 * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD 531 * METHOD}. 532 */ 533 public int getSort() { 534 return sort; 535 } 536 537 /** 538 * Returns the number of dimensions of this array type. This method should 539 * only be used for an array type. 540 * 541 * @return the number of dimensions of this array type. 542 */ 543 public int getDimensions() { 544 int i = 1; 545 while (buf[off + i] == '[') { 546 ++i; 547 } 548 return i; 549 } 550 551 /** 552 * Returns the type of the elements of this array type. This method should 553 * only be used for an array type. 554 * 555 * @return Returns the type of the elements of this array type. 556 */ 557 public Type getElementType() { 558 return getType(buf, off + getDimensions()); 559 } 560 561 /** 562 * Returns the binary name of the class corresponding to this type. This 563 * method must not be used on method types. 564 * 565 * @return the binary name of the class corresponding to this type. 566 */ 567 public String getClassName() { 568 switch (sort) { 569 case VOID: 570 return "void"; 571 case BOOLEAN: 572 return "boolean"; 573 case CHAR: 574 return "char"; 575 case BYTE: 576 return "byte"; 577 case SHORT: 578 return "short"; 579 case INT: 580 return "int"; 581 case FLOAT: 582 return "float"; 583 case LONG: 584 return "long"; 585 case DOUBLE: 586 return "double"; 587 case ARRAY: 588 StringBuffer b = new StringBuffer(getElementType().getClassName()); 589 for (int i = getDimensions(); i > 0; --i) { 590 b.append("[]"); 591 } 592 return b.toString(); 593 case OBJECT: 594 return new String(buf, off, len).replace('/', '.'); 595 default: 596 return null; 597 } 598 } 599 600 /** 601 * Returns the internal name of the class corresponding to this object or 602 * array type. The internal name of a class is its fully qualified name (as 603 * returned by Class.getName(), where '.' are replaced by '/'. This method 604 * should only be used for an object or array type. 605 * 606 * @return the internal name of the class corresponding to this object type. 607 */ 608 public String getInternalName() { 609 return new String(buf, off, len); 610 } 611 612 /** 613 * Returns the argument types of methods of this type. This method should 614 * only be used for method types. 615 * 616 * @return the argument types of methods of this type. 617 */ 618 public Type[] getArgumentTypes() { 619 return getArgumentTypes(getDescriptor()); 620 } 621 622 /** 623 * Returns the return type of methods of this type. This method should only 624 * be used for method types. 625 * 626 * @return the return type of methods of this type. 627 */ 628 public Type getReturnType() { 629 return getReturnType(getDescriptor()); 630 } 631 632 /** 633 * Returns the size of the arguments and of the return value of methods of 634 * this type. This method should only be used for method types. 635 * 636 * @return the size of the arguments (plus one for the implicit this 637 * argument), argSize, and the size of the return value, retSize, 638 * packed into a single 639 * int i = <tt>(argSize << 2) | retSize</tt> 640 * (argSize is therefore equal to <tt>i >> 2</tt>, 641 * and retSize to <tt>i & 0x03</tt>). 642 */ 643 public int getArgumentsAndReturnSizes() { 644 return getArgumentsAndReturnSizes(getDescriptor()); 645 } 646 647 // ------------------------------------------------------------------------ 648 // Conversion to type descriptors 649 // ------------------------------------------------------------------------ 650 651 /** 652 * Returns the descriptor corresponding to this Java type. 653 * 654 * @return the descriptor corresponding to this Java type. 655 */ 656 public String getDescriptor() { 657 StringBuffer buf = new StringBuffer(); 658 getDescriptor(buf); 659 return buf.toString(); 660 } 661 662 /** 663 * Returns the descriptor corresponding to the given argument and return 664 * types. 665 * 666 * @param returnType 667 * the return type of the method. 668 * @param argumentTypes 669 * the argument types of the method. 670 * @return the descriptor corresponding to the given argument and return 671 * types. 672 */ 673 public static String getMethodDescriptor(final Type returnType, 674 final Type... argumentTypes) { 675 StringBuffer buf = new StringBuffer(); 676 buf.append('('); 677 for (int i = 0; i < argumentTypes.length; ++i) { 678 argumentTypes[i].getDescriptor(buf); 679 } 680 buf.append(')'); 681 returnType.getDescriptor(buf); 682 return buf.toString(); 683 } 684 685 /** 686 * Appends the descriptor corresponding to this Java type to the given 687 * string buffer. 688 * 689 * @param buf 690 * the string buffer to which the descriptor must be appended. 691 */ 692 private void getDescriptor(final StringBuffer buf) { 693 if (this.buf == null) { 694 // descriptor is in byte 3 of 'off' for primitive types (buf == 695 // null) 696 buf.append((char) ((off & 0xFF000000) >>> 24)); 697 } else if (sort == OBJECT) { 698 buf.append('L'); 699 buf.append(this.buf, off, len); 700 buf.append(';'); 701 } else { // sort == ARRAY || sort == METHOD 702 buf.append(this.buf, off, len); 703 } 704 } 705 706 // ------------------------------------------------------------------------ 707 // Direct conversion from classes to type descriptors, 708 // without intermediate Type objects 709 // ------------------------------------------------------------------------ 710 711 /** 712 * Returns the internal name of the given class. The internal name of a 713 * class is its fully qualified name, as returned by Class.getName(), where 714 * '.' are replaced by '/'. 715 * 716 * @param c 717 * an object or array class. 718 * @return the internal name of the given class. 719 */ 720 public static String getInternalName(final Class<?> c) { 721 return c.getName().replace('.', '/'); 722 } 723 724 /** 725 * Returns the descriptor corresponding to the given Java type. 726 * 727 * @param c 728 * an object class, a primitive class or an array class. 729 * @return the descriptor corresponding to the given class. 730 */ 731 public static String getDescriptor(final Class<?> c) { 732 StringBuffer buf = new StringBuffer(); 733 getDescriptor(buf, c); 734 return buf.toString(); 735 } 736 737 /** 738 * Returns the descriptor corresponding to the given constructor. 739 * 740 * @param c 741 * a {@link Constructor Constructor} object. 742 * @return the descriptor of the given constructor. 743 */ 744 public static String getConstructorDescriptor(final Constructor<?> c) { 745 Class<?>[] parameters = c.getParameterTypes(); 746 StringBuffer buf = new StringBuffer(); 747 buf.append('('); 748 for (int i = 0; i < parameters.length; ++i) { 749 getDescriptor(buf, parameters[i]); 750 } 751 return buf.append(")V").toString(); 752 } 753 754 /** 755 * Returns the descriptor corresponding to the given method. 756 * 757 * @param m 758 * a {@link Method Method} object. 759 * @return the descriptor of the given method. 760 */ 761 public static String getMethodDescriptor(final Method m) { 762 Class<?>[] parameters = m.getParameterTypes(); 763 StringBuffer buf = new StringBuffer(); 764 buf.append('('); 765 for (int i = 0; i < parameters.length; ++i) { 766 getDescriptor(buf, parameters[i]); 767 } 768 buf.append(')'); 769 getDescriptor(buf, m.getReturnType()); 770 return buf.toString(); 771 } 772 773 /** 774 * Appends the descriptor of the given class to the given string buffer. 775 * 776 * @param buf 777 * the string buffer to which the descriptor must be appended. 778 * @param c 779 * the class whose descriptor must be computed. 780 */ 781 private static void getDescriptor(final StringBuffer buf, final Class<?> c) { 782 Class<?> d = c; 783 while (true) { 784 if (d.isPrimitive()) { 785 char car; 786 if (d == Integer.TYPE) { 787 car = 'I'; 788 } else if (d == Void.TYPE) { 789 car = 'V'; 790 } else if (d == Boolean.TYPE) { 791 car = 'Z'; 792 } else if (d == Byte.TYPE) { 793 car = 'B'; 794 } else if (d == Character.TYPE) { 795 car = 'C'; 796 } else if (d == Short.TYPE) { 797 car = 'S'; 798 } else if (d == Double.TYPE) { 799 car = 'D'; 800 } else if (d == Float.TYPE) { 801 car = 'F'; 802 } else /* if (d == Long.TYPE) */{ 803 car = 'J'; 804 } 805 buf.append(car); 806 return; 807 } else if (d.isArray()) { 808 buf.append('['); 809 d = d.getComponentType(); 810 } else { 811 buf.append('L'); 812 String name = d.getName(); 813 int len = name.length(); 814 for (int i = 0; i < len; ++i) { 815 char car = name.charAt(i); 816 buf.append(car == '.' ? '/' : car); 817 } 818 buf.append(';'); 819 return; 820 } 821 } 822 } 823 824 // ------------------------------------------------------------------------ 825 // Corresponding size and opcodes 826 // ------------------------------------------------------------------------ 827 828 /** 829 * Returns the size of values of this type. This method must not be used for 830 * method types. 831 * 832 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and 833 * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. 834 */ 835 public int getSize() { 836 // the size is in byte 0 of 'off' for primitive types (buf == null) 837 return buf == null ? (off & 0xFF) : 1; 838 } 839 840 /** 841 * Returns a JVM instruction opcode adapted to this Java type. This method 842 * must not be used for method types. 843 * 844 * @param opcode 845 * a JVM instruction opcode. This opcode must be one of ILOAD, 846 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, 847 * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. 848 * @return an opcode that is similar to the given opcode, but adapted to 849 * this Java type. For example, if this type is <tt>float</tt> and 850 * <tt>opcode</tt> is IRETURN, this method returns FRETURN. 851 */ 852 public int getOpcode(final int opcode) { 853 if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { 854 // the offset for IALOAD or IASTORE is in byte 1 of 'off' for 855 // primitive types (buf == null) 856 return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); 857 } else { 858 // the offset for other instructions is in byte 2 of 'off' for 859 // primitive types (buf == null) 860 return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); 861 } 862 } 863 864 // ------------------------------------------------------------------------ 865 // Equals, hashCode and toString 866 // ------------------------------------------------------------------------ 867 868 /** 869 * Tests if the given object is equal to this type. 870 * 871 * @param o 872 * the object to be compared to this type. 873 * @return <tt>true</tt> if the given object is equal to this type. 874 */ 875 @Override 876 public boolean equals(final Object o) { 877 if (this == o) { 878 return true; 879 } 880 if (!(o instanceof Type)) { 881 return false; 882 } 883 Type t = (Type) o; 884 if (sort != t.sort) { 885 return false; 886 } 887 if (sort >= ARRAY) { 888 if (len != t.len) { 889 return false; 890 } 891 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 892 if (buf[i] != t.buf[j]) { 893 return false; 894 } 895 } 896 } 897 return true; 898 } 899 900 /** 901 * Returns a hash code value for this type. 902 * 903 * @return a hash code value for this type. 904 */ 905 @Override 906 public int hashCode() { 907 int hc = 13 * sort; 908 if (sort >= ARRAY) { 909 for (int i = off, end = i + len; i < end; i++) { 910 hc = 17 * (hc + buf[i]); 911 } 912 } 913 return hc; 914 } 915 916 /** 917 * Returns a string representation of this type. 918 * 919 * @return the descriptor of this type. 920 */ 921 @Override 922 public String toString() { 923 return getDescriptor(); 924 } 925 }