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 int off = 1; 410 while (true) { 411 char car = buf[off++]; 412 if (car == ')') { 413 return getType(buf, off); 414 } else if (car == 'L') { 415 while (buf[off++] != ';') { 416 } 417 } 418 } 419 } 420 421 /** 422 * Returns the Java type corresponding to the return type of the given 423 * method. 424 * 425 * @param method 426 * a method. 427 * @return the Java type corresponding to the return type of the given 428 * method. 429 */ 430 public static Type getReturnType(final Method method) { 431 return getType(method.getReturnType()); 432 } 433 434 /** 435 * Computes the size of the arguments and of the return value of a method. 436 * 437 * @param desc 438 * the descriptor of a method. 439 * @return the size of the arguments of the method (plus one for the 440 * implicit this argument), argSize, and the size of its return 441 * value, retSize, packed into a single int i = 442 * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to 443 * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). 444 */ 445 public static int getArgumentsAndReturnSizes(final String desc) { 446 int n = 1; 447 int c = 1; 448 while (true) { 449 char car = desc.charAt(c++); 450 if (car == ')') { 451 car = desc.charAt(c); 452 return n << 2 453 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 454 } else if (car == 'L') { 455 while (desc.charAt(c++) != ';') { 456 } 457 n += 1; 458 } else if (car == '[') { 459 while ((car = desc.charAt(c)) == '[') { 460 ++c; 461 } 462 if (car == 'D' || car == 'J') { 463 n -= 1; 464 } 465 } else if (car == 'D' || car == 'J') { 466 n += 2; 467 } else { 468 n += 1; 469 } 470 } 471 } 472 473 /** 474 * Returns the Java type corresponding to the given type descriptor. For 475 * method descriptors, buf is supposed to contain nothing more than the 476 * descriptor itself. 477 * 478 * @param buf 479 * a buffer containing a type descriptor. 480 * @param off 481 * the offset of this descriptor in the previous buffer. 482 * @return the Java type corresponding to the given type descriptor. 483 */ 484 private static Type getType(final char[] buf, final int off) { 485 int len; 486 switch (buf[off]) { 487 case 'V': 488 return VOID_TYPE; 489 case 'Z': 490 return BOOLEAN_TYPE; 491 case 'C': 492 return CHAR_TYPE; 493 case 'B': 494 return BYTE_TYPE; 495 case 'S': 496 return SHORT_TYPE; 497 case 'I': 498 return INT_TYPE; 499 case 'F': 500 return FLOAT_TYPE; 501 case 'J': 502 return LONG_TYPE; 503 case 'D': 504 return DOUBLE_TYPE; 505 case '[': 506 len = 1; 507 while (buf[off + len] == '[') { 508 ++len; 509 } 510 if (buf[off + len] == 'L') { 511 ++len; 512 while (buf[off + len] != ';') { 513 ++len; 514 } 515 } 516 return new Type(ARRAY, buf, off, len + 1); 517 case 'L': 518 len = 1; 519 while (buf[off + len] != ';') { 520 ++len; 521 } 522 return new Type(OBJECT, buf, off + 1, len - 1); 523 // case '(': 524 default: 525 return new Type(METHOD, buf, off, buf.length - off); 526 } 527 } 528 529 // ------------------------------------------------------------------------ 530 // Accessors 531 // ------------------------------------------------------------------------ 532 533 /** 534 * Returns the sort of this Java type. 535 * 536 * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, 537 * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, 538 * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, 539 * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD 540 * METHOD}. 541 */ 542 public int getSort() { 543 return sort; 544 } 545 546 /** 547 * Returns the number of dimensions of this array type. This method should 548 * only be used for an array type. 549 * 550 * @return the number of dimensions of this array type. 551 */ 552 public int getDimensions() { 553 int i = 1; 554 while (buf[off + i] == '[') { 555 ++i; 556 } 557 return i; 558 } 559 560 /** 561 * Returns the type of the elements of this array type. This method should 562 * only be used for an array type. 563 * 564 * @return Returns the type of the elements of this array type. 565 */ 566 public Type getElementType() { 567 return getType(buf, off + getDimensions()); 568 } 569 570 /** 571 * Returns the binary name of the class corresponding to this type. This 572 * method must not be used on method types. 573 * 574 * @return the binary name of the class corresponding to this type. 575 */ 576 public String getClassName() { 577 switch (sort) { 578 case VOID: 579 return "void"; 580 case BOOLEAN: 581 return "boolean"; 582 case CHAR: 583 return "char"; 584 case BYTE: 585 return "byte"; 586 case SHORT: 587 return "short"; 588 case INT: 589 return "int"; 590 case FLOAT: 591 return "float"; 592 case LONG: 593 return "long"; 594 case DOUBLE: 595 return "double"; 596 case ARRAY: 597 StringBuilder sb = new StringBuilder(getElementType().getClassName()); 598 for (int i = getDimensions(); i > 0; --i) { 599 sb.append("[]"); 600 } 601 return sb.toString(); 602 case OBJECT: 603 return new String(buf, off, len).replace('/', '.'); 604 default: 605 return null; 606 } 607 } 608 609 /** 610 * Returns the internal name of the class corresponding to this object or 611 * array type. The internal name of a class is its fully qualified name (as 612 * returned by Class.getName(), where '.' are replaced by '/'. This method 613 * should only be used for an object or array type. 614 * 615 * @return the internal name of the class corresponding to this object type. 616 */ 617 public String getInternalName() { 618 return new String(buf, off, len); 619 } 620 621 /** 622 * Returns the argument types of methods of this type. This method should 623 * only be used for method types. 624 * 625 * @return the argument types of methods of this type. 626 */ 627 public Type[] getArgumentTypes() { 628 return getArgumentTypes(getDescriptor()); 629 } 630 631 /** 632 * Returns the return type of methods of this type. This method should only 633 * be used for method types. 634 * 635 * @return the return type of methods of this type. 636 */ 637 public Type getReturnType() { 638 return getReturnType(getDescriptor()); 639 } 640 641 /** 642 * Returns the size of the arguments and of the return value of methods of 643 * this type. This method should only be used for method types. 644 * 645 * @return the size of the arguments (plus one for the implicit this 646 * argument), argSize, and the size of the return value, retSize, 647 * packed into a single 648 * int i = <tt>(argSize << 2) | retSize</tt> 649 * (argSize is therefore equal to <tt>i >> 2</tt>, 650 * and retSize to <tt>i & 0x03</tt>). 651 */ 652 public int getArgumentsAndReturnSizes() { 653 return getArgumentsAndReturnSizes(getDescriptor()); 654 } 655 656 // ------------------------------------------------------------------------ 657 // Conversion to type descriptors 658 // ------------------------------------------------------------------------ 659 660 /** 661 * Returns the descriptor corresponding to this Java type. 662 * 663 * @return the descriptor corresponding to this Java type. 664 */ 665 public String getDescriptor() { 666 StringBuilder buf = new StringBuilder(); 667 getDescriptor(buf); 668 return buf.toString(); 669 } 670 671 /** 672 * Returns the descriptor corresponding to the given argument and return 673 * types. 674 * 675 * @param returnType 676 * the return type of the method. 677 * @param argumentTypes 678 * the argument types of the method. 679 * @return the descriptor corresponding to the given argument and return 680 * types. 681 */ 682 public static String getMethodDescriptor(final Type returnType, 683 final Type... argumentTypes) { 684 StringBuilder buf = new StringBuilder(); 685 buf.append('('); 686 for (int i = 0; i < argumentTypes.length; ++i) { 687 argumentTypes[i].getDescriptor(buf); 688 } 689 buf.append(')'); 690 returnType.getDescriptor(buf); 691 return buf.toString(); 692 } 693 694 /** 695 * Appends the descriptor corresponding to this Java type to the given 696 * string buffer. 697 * 698 * @param buf 699 * the string buffer to which the descriptor must be appended. 700 */ 701 private void getDescriptor(final StringBuilder buf) { 702 if (this.buf == null) { 703 // descriptor is in byte 3 of 'off' for primitive types (buf == 704 // null) 705 buf.append((char) ((off & 0xFF000000) >>> 24)); 706 } else if (sort == OBJECT) { 707 buf.append('L'); 708 buf.append(this.buf, off, len); 709 buf.append(';'); 710 } else { // sort == ARRAY || sort == METHOD 711 buf.append(this.buf, off, len); 712 } 713 } 714 715 // ------------------------------------------------------------------------ 716 // Direct conversion from classes to type descriptors, 717 // without intermediate Type objects 718 // ------------------------------------------------------------------------ 719 720 /** 721 * Returns the internal name of the given class. The internal name of a 722 * class is its fully qualified name, as returned by Class.getName(), where 723 * '.' are replaced by '/'. 724 * 725 * @param c 726 * an object or array class. 727 * @return the internal name of the given class. 728 */ 729 public static String getInternalName(final Class<?> c) { 730 return c.getName().replace('.', '/'); 731 } 732 733 /** 734 * Returns the descriptor corresponding to the given Java type. 735 * 736 * @param c 737 * an object class, a primitive class or an array class. 738 * @return the descriptor corresponding to the given class. 739 */ 740 public static String getDescriptor(final Class<?> c) { 741 StringBuilder buf = new StringBuilder(); 742 getDescriptor(buf, c); 743 return buf.toString(); 744 } 745 746 /** 747 * Returns the descriptor corresponding to the given constructor. 748 * 749 * @param c 750 * a {@link Constructor Constructor} object. 751 * @return the descriptor of the given constructor. 752 */ 753 public static String getConstructorDescriptor(final Constructor<?> c) { 754 Class<?>[] parameters = c.getParameterTypes(); 755 StringBuilder buf = new StringBuilder(); 756 buf.append('('); 757 for (int i = 0; i < parameters.length; ++i) { 758 getDescriptor(buf, parameters[i]); 759 } 760 return buf.append(")V").toString(); 761 } 762 763 /** 764 * Returns the descriptor corresponding to the given method. 765 * 766 * @param m 767 * a {@link Method Method} object. 768 * @return the descriptor of the given method. 769 */ 770 public static String getMethodDescriptor(final Method m) { 771 Class<?>[] parameters = m.getParameterTypes(); 772 StringBuilder buf = new StringBuilder(); 773 buf.append('('); 774 for (int i = 0; i < parameters.length; ++i) { 775 getDescriptor(buf, parameters[i]); 776 } 777 buf.append(')'); 778 getDescriptor(buf, m.getReturnType()); 779 return buf.toString(); 780 } 781 782 /** 783 * Appends the descriptor of the given class to the given string buffer. 784 * 785 * @param buf 786 * the string buffer to which the descriptor must be appended. 787 * @param c 788 * the class whose descriptor must be computed. 789 */ 790 private static void getDescriptor(final StringBuilder buf, final Class<?> c) { 791 Class<?> d = c; 792 while (true) { 793 if (d.isPrimitive()) { 794 char car; 795 if (d == Integer.TYPE) { 796 car = 'I'; 797 } else if (d == Void.TYPE) { 798 car = 'V'; 799 } else if (d == Boolean.TYPE) { 800 car = 'Z'; 801 } else if (d == Byte.TYPE) { 802 car = 'B'; 803 } else if (d == Character.TYPE) { 804 car = 'C'; 805 } else if (d == Short.TYPE) { 806 car = 'S'; 807 } else if (d == Double.TYPE) { 808 car = 'D'; 809 } else if (d == Float.TYPE) { 810 car = 'F'; 811 } else /* if (d == Long.TYPE) */{ 812 car = 'J'; 813 } 814 buf.append(car); 815 return; 816 } else if (d.isArray()) { 817 buf.append('['); 818 d = d.getComponentType(); 819 } else { 820 buf.append('L'); 821 String name = d.getName(); 822 int len = name.length(); 823 for (int i = 0; i < len; ++i) { 824 char car = name.charAt(i); 825 buf.append(car == '.' ? '/' : car); 826 } 827 buf.append(';'); 828 return; 829 } 830 } 831 } 832 833 // ------------------------------------------------------------------------ 834 // Corresponding size and opcodes 835 // ------------------------------------------------------------------------ 836 837 /** 838 * Returns the size of values of this type. This method must not be used for 839 * method types. 840 * 841 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and 842 * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. 843 */ 844 public int getSize() { 845 // the size is in byte 0 of 'off' for primitive types (buf == null) 846 return buf == null ? (off & 0xFF) : 1; 847 } 848 849 /** 850 * Returns a JVM instruction opcode adapted to this Java type. This method 851 * must not be used for method types. 852 * 853 * @param opcode 854 * a JVM instruction opcode. This opcode must be one of ILOAD, 855 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, 856 * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. 857 * @return an opcode that is similar to the given opcode, but adapted to 858 * this Java type. For example, if this type is <tt>float</tt> and 859 * <tt>opcode</tt> is IRETURN, this method returns FRETURN. 860 */ 861 public int getOpcode(final int opcode) { 862 if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { 863 // the offset for IALOAD or IASTORE is in byte 1 of 'off' for 864 // primitive types (buf == null) 865 return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); 866 } else { 867 // the offset for other instructions is in byte 2 of 'off' for 868 // primitive types (buf == null) 869 return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); 870 } 871 } 872 873 // ------------------------------------------------------------------------ 874 // Equals, hashCode and toString 875 // ------------------------------------------------------------------------ 876 877 /** 878 * Tests if the given object is equal to this type. 879 * 880 * @param o 881 * the object to be compared to this type. 882 * @return <tt>true</tt> if the given object is equal to this type. 883 */ 884 @Override 885 public boolean equals(final Object o) { 886 if (this == o) { 887 return true; 888 } 889 if (!(o instanceof Type)) { 890 return false; 891 } 892 Type t = (Type) o; 893 if (sort != t.sort) { 894 return false; 895 } 896 if (sort >= ARRAY) { 897 if (len != t.len) { 898 return false; 899 } 900 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 901 if (buf[i] != t.buf[j]) { 902 return false; 903 } 904 } 905 } 906 return true; 907 } 908 909 /** 910 * Returns a hash code value for this type. 911 * 912 * @return a hash code value for this type. 913 */ 914 @Override 915 public int hashCode() { 916 int hc = 13 * sort; 917 if (sort >= ARRAY) { 918 for (int i = off, end = i + len; i < end; i++) { 919 hc = 17 * (hc + buf[i]); 920 } 921 } 922 return hc; 923 } 924 925 /** 926 * Returns a string representation of this type. 927 * 928 * @return the descriptor of this type. 929 */ 930 @Override 931 public String toString() { 932 return getDescriptor(); 933 } 934 }