< prev index next >

src/java.base/share/classes/jdk/internal/org/objectweb/asm/Type.java

Print this page

 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 manipulate type and
 66  * method descriptors.
 67  *
 68  * @author Eric Bruneton
 69  * @author Chris Nokleberg
 70  */
 71 public final class Type {
 72 
 73     /** The sort of the {@code void} type. See {@link #getSort}. */
 74     public static final int VOID = 0;
 75 
 76     /** The sort of the {@code boolean} type. See {@link #getSort}. */
 77     public static final int BOOLEAN = 1;
 78 
 79     /** The sort of the {@code char} type. See {@link #getSort}. */
 80     public static final int CHAR = 2;
 81 

317     }
318 
319     /**
320       * Returns the {@link Type} values corresponding to the argument types of the given method
321       * descriptor.
322       *
323       * @param methodDescriptor a method descriptor.
324       * @return the {@link Type} values corresponding to the argument types of the given method
325       *     descriptor.
326       */
327     public static Type[] getArgumentTypes(final String methodDescriptor) {
328         // First step: compute the number of argument types in methodDescriptor.
329         int numArgumentTypes = 0;
330         // Skip the first character, which is always a '('.
331         int currentOffset = 1;
332         // Parse the argument types, one at a each loop iteration.
333         while (methodDescriptor.charAt(currentOffset) != ')') {
334             while (methodDescriptor.charAt(currentOffset) == '[') {
335                 currentOffset++;
336             }
337             if (methodDescriptor.charAt(currentOffset++) == 'L') {

338                 // Skip the argument descriptor content.
339                 int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
340                 currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
341             }
342             ++numArgumentTypes;
343         }
344 
345         // Second step: create a Type instance for each argument type.
346         Type[] argumentTypes = new Type[numArgumentTypes];
347         // Skip the first character, which is always a '('.
348         currentOffset = 1;
349         // Parse and create the argument types, one at each loop iteration.
350         int currentArgumentTypeIndex = 0;
351         while (methodDescriptor.charAt(currentOffset) != ')') {
352             final int currentArgumentTypeOffset = currentOffset;
353             while (methodDescriptor.charAt(currentOffset) == '[') {
354                 currentOffset++;
355             }
356             if (methodDescriptor.charAt(currentOffset++) == 'L') {

357                 // Skip the argument descriptor content.
358                 int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
359                 currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
360             }
361             argumentTypes[currentArgumentTypeIndex++] =
362                     getTypeInternal(methodDescriptor, currentArgumentTypeOffset, currentOffset);
363         }
364         return argumentTypes;
365     }
366 
367     /**
368       * Returns the {@link Type} values corresponding to the argument types of the given method.
369       *
370       * @param method a method.
371       * @return the {@link Type} values corresponding to the argument types of the given method.
372       */
373     public static Type[] getArgumentTypes(final Method method) {
374         Class<?>[] classes = method.getParameterTypes();
375         Type[] types = new Type[classes.length];
376         for (int i = classes.length - 1; i >= 0; --i) {

407       * @return the {@link Type} corresponding to the return type of the given method.
408       */
409     public static Type getReturnType(final Method method) {
410         return getType(method.getReturnType());
411     }
412 
413     /**
414       * Returns the start index of the return type of the given method descriptor.
415       *
416       * @param methodDescriptor a method descriptor.
417       * @return the start index of the return type of the given method descriptor.
418       */
419     static int getReturnTypeOffset(final String methodDescriptor) {
420         // Skip the first character, which is always a '('.
421         int currentOffset = 1;
422         // Skip the argument types, one at a each loop iteration.
423         while (methodDescriptor.charAt(currentOffset) != ')') {
424             while (methodDescriptor.charAt(currentOffset) == '[') {
425                 currentOffset++;
426             }
427             if (methodDescriptor.charAt(currentOffset++) == 'L') {

428                 // Skip the argument descriptor content.
429                 int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
430                 currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
431             }
432         }
433         return currentOffset + 1;
434     }
435 
436     /**
437       * Returns the {@link Type} corresponding to the given field or method descriptor.
438       *
439       * @param descriptorBuffer a buffer containing the field or method descriptor.
440       * @param descriptorBegin the beginning index, inclusive, of the field or method descriptor in
441       *     descriptorBuffer.
442       * @param descriptorEnd the end index, exclusive, of the field or method descriptor in
443       *     descriptorBuffer.
444       * @return the {@link Type} corresponding to the given type descriptor.
445       */
446     private static Type getTypeInternal(
447             final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) {

450                 return VOID_TYPE;
451             case 'Z':
452                 return BOOLEAN_TYPE;
453             case 'C':
454                 return CHAR_TYPE;
455             case 'B':
456                 return BYTE_TYPE;
457             case 'S':
458                 return SHORT_TYPE;
459             case 'I':
460                 return INT_TYPE;
461             case 'F':
462                 return FLOAT_TYPE;
463             case 'J':
464                 return LONG_TYPE;
465             case 'D':
466                 return DOUBLE_TYPE;
467             case '[':
468                 return new Type(ARRAY, descriptorBuffer, descriptorBegin, descriptorEnd);
469             case 'L':

470                 return new Type(OBJECT, descriptorBuffer, descriptorBegin + 1, descriptorEnd - 1);
471             case '(':
472                 return new Type(METHOD, descriptorBuffer, descriptorBegin, descriptorEnd);
473             default:
474                 throw new IllegalArgumentException();
475         }
476     }
477 
478     // -----------------------------------------------------------------------------------------------
479     // Methods to get class names, internal names or descriptors.
480     // -----------------------------------------------------------------------------------------------
481 
482     /**
483       * Returns the binary name of the class corresponding to this type. This method must not be used
484       * on method types.
485       *
486       * @return the binary name of the class corresponding to this type.
487       */
488     public String getClassName() {
489         switch (sort) {

655                 descriptor = 'V';
656             } else if (currentClass == Boolean.TYPE) {
657                 descriptor = 'Z';
658             } else if (currentClass == Byte.TYPE) {
659                 descriptor = 'B';
660             } else if (currentClass == Character.TYPE) {
661                 descriptor = 'C';
662             } else if (currentClass == Short.TYPE) {
663                 descriptor = 'S';
664             } else if (currentClass == Double.TYPE) {
665                 descriptor = 'D';
666             } else if (currentClass == Float.TYPE) {
667                 descriptor = 'F';
668             } else if (currentClass == Long.TYPE) {
669                 descriptor = 'J';
670             } else {
671                 throw new AssertionError();
672             }
673             stringBuilder.append(descriptor);
674         } else {
675             stringBuilder.append('L').append(getInternalName(currentClass)).append(';');
676         }
677     }
678 





679     // -----------------------------------------------------------------------------------------------
680     // Methods to get the sort, dimension, size, and opcodes corresponding to a Type or descriptor.
681     // -----------------------------------------------------------------------------------------------
682 
683     /**
684       * Returns the sort of this type.
685       *
686       * @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link
687       *     #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or
688       *     {@link #METHOD}.
689       */
690     public int getSort() {
691         return sort == INTERNAL ? OBJECT : sort;
692     }
693 
694     /**
695       * Returns the number of dimensions of this array type. This method should only be used for an
696       * array type.
697       *
698       * @return the number of dimensions of this array type.

752       * @param methodDescriptor a method descriptor.
753       * @return the size of the arguments of the method (plus one for the implicit this argument),
754       *     argumentsSize, and the size of its return value, returnSize, packed into a single int i =
755       *     {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
756       *     i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
757       */
758     public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
759         int argumentsSize = 1;
760         // Skip the first character, which is always a '('.
761         int currentOffset = 1;
762         int currentChar = methodDescriptor.charAt(currentOffset);
763         // Parse the argument types and compute their size, one at a each loop iteration.
764         while (currentChar != ')') {
765             if (currentChar == 'J' || currentChar == 'D') {
766                 currentOffset++;
767                 argumentsSize += 2;
768             } else {
769                 while (methodDescriptor.charAt(currentOffset) == '[') {
770                     currentOffset++;
771                 }
772                 if (methodDescriptor.charAt(currentOffset++) == 'L') {

773                     // Skip the argument descriptor content.
774                     int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
775                     currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
776                 }
777                 argumentsSize += 1;
778             }
779             currentChar = methodDescriptor.charAt(currentOffset);
780         }
781         currentChar = methodDescriptor.charAt(currentOffset + 1);
782         if (currentChar == 'V') {
783             return argumentsSize << 2;
784         } else {
785             int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1;
786             return argumentsSize << 2 | returnSize;
787         }
788     }
789 
790     /**
791       * Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for
792       * method types.

 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.InvocationTargetException;
 63 import java.lang.reflect.Method;
 64 
 65 /**
 66  * A Java field or method type. This class can be used to make it easier to manipulate type and
 67  * method descriptors.
 68  *
 69  * @author Eric Bruneton
 70  * @author Chris Nokleberg
 71  */
 72 public final class Type {
 73 
 74     /** The sort of the {@code void} type. See {@link #getSort}. */
 75     public static final int VOID = 0;
 76 
 77     /** The sort of the {@code boolean} type. See {@link #getSort}. */
 78     public static final int BOOLEAN = 1;
 79 
 80     /** The sort of the {@code char} type. See {@link #getSort}. */
 81     public static final int CHAR = 2;
 82 

318     }
319 
320     /**
321       * Returns the {@link Type} values corresponding to the argument types of the given method
322       * descriptor.
323       *
324       * @param methodDescriptor a method descriptor.
325       * @return the {@link Type} values corresponding to the argument types of the given method
326       *     descriptor.
327       */
328     public static Type[] getArgumentTypes(final String methodDescriptor) {
329         // First step: compute the number of argument types in methodDescriptor.
330         int numArgumentTypes = 0;
331         // Skip the first character, which is always a '('.
332         int currentOffset = 1;
333         // Parse the argument types, one at a each loop iteration.
334         while (methodDescriptor.charAt(currentOffset) != ')') {
335             while (methodDescriptor.charAt(currentOffset) == '[') {
336                 currentOffset++;
337             }
338             char c = methodDescriptor.charAt(currentOffset++);
339             if (c == 'L' || c == 'Q') {
340                 // Skip the argument descriptor content.
341                 int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
342                 currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
343             }
344             ++numArgumentTypes;
345         }
346 
347         // Second step: create a Type instance for each argument type.
348         Type[] argumentTypes = new Type[numArgumentTypes];
349         // Skip the first character, which is always a '('.
350         currentOffset = 1;
351         // Parse and create the argument types, one at each loop iteration.
352         int currentArgumentTypeIndex = 0;
353         while (methodDescriptor.charAt(currentOffset) != ')') {
354             final int currentArgumentTypeOffset = currentOffset;
355             while (methodDescriptor.charAt(currentOffset) == '[') {
356                 currentOffset++;
357             }
358             char c = methodDescriptor.charAt(currentOffset++);
359             if (c == 'L' || c == 'Q') {
360                 // Skip the argument descriptor content.
361                 int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
362                 currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
363             }
364             argumentTypes[currentArgumentTypeIndex++] =
365                     getTypeInternal(methodDescriptor, currentArgumentTypeOffset, currentOffset);
366         }
367         return argumentTypes;
368     }
369 
370     /**
371       * Returns the {@link Type} values corresponding to the argument types of the given method.
372       *
373       * @param method a method.
374       * @return the {@link Type} values corresponding to the argument types of the given method.
375       */
376     public static Type[] getArgumentTypes(final Method method) {
377         Class<?>[] classes = method.getParameterTypes();
378         Type[] types = new Type[classes.length];
379         for (int i = classes.length - 1; i >= 0; --i) {

410       * @return the {@link Type} corresponding to the return type of the given method.
411       */
412     public static Type getReturnType(final Method method) {
413         return getType(method.getReturnType());
414     }
415 
416     /**
417       * Returns the start index of the return type of the given method descriptor.
418       *
419       * @param methodDescriptor a method descriptor.
420       * @return the start index of the return type of the given method descriptor.
421       */
422     static int getReturnTypeOffset(final String methodDescriptor) {
423         // Skip the first character, which is always a '('.
424         int currentOffset = 1;
425         // Skip the argument types, one at a each loop iteration.
426         while (methodDescriptor.charAt(currentOffset) != ')') {
427             while (methodDescriptor.charAt(currentOffset) == '[') {
428                 currentOffset++;
429             }
430             char c = methodDescriptor.charAt(currentOffset++);
431             if (c == 'L' || c == 'Q') {
432                 // Skip the argument descriptor content.
433                 int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
434                 currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
435             }
436         }
437         return currentOffset + 1;
438     }
439 
440     /**
441       * Returns the {@link Type} corresponding to the given field or method descriptor.
442       *
443       * @param descriptorBuffer a buffer containing the field or method descriptor.
444       * @param descriptorBegin the beginning index, inclusive, of the field or method descriptor in
445       *     descriptorBuffer.
446       * @param descriptorEnd the end index, exclusive, of the field or method descriptor in
447       *     descriptorBuffer.
448       * @return the {@link Type} corresponding to the given type descriptor.
449       */
450     private static Type getTypeInternal(
451             final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) {

454                 return VOID_TYPE;
455             case 'Z':
456                 return BOOLEAN_TYPE;
457             case 'C':
458                 return CHAR_TYPE;
459             case 'B':
460                 return BYTE_TYPE;
461             case 'S':
462                 return SHORT_TYPE;
463             case 'I':
464                 return INT_TYPE;
465             case 'F':
466                 return FLOAT_TYPE;
467             case 'J':
468                 return LONG_TYPE;
469             case 'D':
470                 return DOUBLE_TYPE;
471             case '[':
472                 return new Type(ARRAY, descriptorBuffer, descriptorBegin, descriptorEnd);
473             case 'L':
474             case 'Q':
475                 return new Type(OBJECT, descriptorBuffer, descriptorBegin + 1, descriptorEnd - 1);
476             case '(':
477                 return new Type(METHOD, descriptorBuffer, descriptorBegin, descriptorEnd);
478             default:
479                 throw new IllegalArgumentException();
480         }
481     }
482 
483     // -----------------------------------------------------------------------------------------------
484     // Methods to get class names, internal names or descriptors.
485     // -----------------------------------------------------------------------------------------------
486 
487     /**
488       * Returns the binary name of the class corresponding to this type. This method must not be used
489       * on method types.
490       *
491       * @return the binary name of the class corresponding to this type.
492       */
493     public String getClassName() {
494         switch (sort) {

660                 descriptor = 'V';
661             } else if (currentClass == Boolean.TYPE) {
662                 descriptor = 'Z';
663             } else if (currentClass == Byte.TYPE) {
664                 descriptor = 'B';
665             } else if (currentClass == Character.TYPE) {
666                 descriptor = 'C';
667             } else if (currentClass == Short.TYPE) {
668                 descriptor = 'S';
669             } else if (currentClass == Double.TYPE) {
670                 descriptor = 'D';
671             } else if (currentClass == Float.TYPE) {
672                 descriptor = 'F';
673             } else if (currentClass == Long.TYPE) {
674                 descriptor = 'J';
675             } else {
676                 throw new AssertionError();
677             }
678             stringBuilder.append(descriptor);
679         } else {
680             stringBuilder.append(isPrimitiveClass(currentClass) ? 'Q' : 'L').append(getInternalName(currentClass)).append(';');
681         }
682     }
683 
684     static boolean isPrimitiveClass(Class<?> clazz) {
685         int mods = clazz.getModifiers();
686         return (mods & 0x00000100) != 0;
687     }
688 
689     // -----------------------------------------------------------------------------------------------
690     // Methods to get the sort, dimension, size, and opcodes corresponding to a Type or descriptor.
691     // -----------------------------------------------------------------------------------------------
692 
693     /**
694       * Returns the sort of this type.
695       *
696       * @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link
697       *     #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or
698       *     {@link #METHOD}.
699       */
700     public int getSort() {
701         return sort == INTERNAL ? OBJECT : sort;
702     }
703 
704     /**
705       * Returns the number of dimensions of this array type. This method should only be used for an
706       * array type.
707       *
708       * @return the number of dimensions of this array type.

762       * @param methodDescriptor a method descriptor.
763       * @return the size of the arguments of the method (plus one for the implicit this argument),
764       *     argumentsSize, and the size of its return value, returnSize, packed into a single int i =
765       *     {@code (argumentsSize &lt;&lt; 2) | returnSize} (argumentsSize is therefore equal to {@code
766       *     i &gt;&gt; 2}, and returnSize to {@code i &amp; 0x03}).
767       */
768     public static int getArgumentsAndReturnSizes(final String methodDescriptor) {
769         int argumentsSize = 1;
770         // Skip the first character, which is always a '('.
771         int currentOffset = 1;
772         int currentChar = methodDescriptor.charAt(currentOffset);
773         // Parse the argument types and compute their size, one at a each loop iteration.
774         while (currentChar != ')') {
775             if (currentChar == 'J' || currentChar == 'D') {
776                 currentOffset++;
777                 argumentsSize += 2;
778             } else {
779                 while (methodDescriptor.charAt(currentOffset) == '[') {
780                     currentOffset++;
781                 }
782                 char c = methodDescriptor.charAt(currentOffset++);
783                 if (c == 'L' || c == 'Q') {
784                     // Skip the argument descriptor content.
785                     int semiColumnOffset = methodDescriptor.indexOf(';', currentOffset);
786                     currentOffset = Math.max(currentOffset, semiColumnOffset + 1);
787                 }
788                 argumentsSize += 1;
789             }
790             currentChar = methodDescriptor.charAt(currentOffset);
791         }
792         currentChar = methodDescriptor.charAt(currentOffset + 1);
793         if (currentChar == 'V') {
794             return argumentsSize << 2;
795         } else {
796             int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1;
797             return argumentsSize << 2 | returnSize;
798         }
799     }
800 
801     /**
802       * Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for
803       * method types.
< prev index next >