1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm; 29 30 import java.util.Arrays; 31 32 /** 33 * A constant whose value is computed at runtime, with a bootstrap method. 34 * 35 * @author Remi Forax 36 */ 37 public final class ConstantDynamic { 38 39 /** The constant name (can be arbitrary). */ 40 private final String name; 41 42 /** The constant type (must be a field descriptor). */ 43 private final String descriptor; 44 45 /** The bootstrap method to use to compute the constant value at runtime. */ 46 private final Handle bootstrapMethod; 47 48 /** 49 * The arguments to pass to the bootstrap method, in order to compute the constant value at 50 * runtime. 51 */ 52 private final Object[] bootstrapMethodArguments; 53 54 /** 55 * Constructs a new {@link ConstantDynamic}. 56 * 57 * @param name the constant name (can be arbitrary). 58 * @param descriptor the constant type (must be a field descriptor). 59 * @param bootstrapMethod the bootstrap method to use to compute the constant value at runtime. 60 * @param bootstrapMethodArguments the arguments to pass to the bootstrap method, in order to 61 * compute the constant value at runtime. 62 */ ConstantDynamic( final String name, final String descriptor, final Handle bootstrapMethod, final Object... bootstrapMethodArguments)63 public ConstantDynamic( 64 final String name, 65 final String descriptor, 66 final Handle bootstrapMethod, 67 final Object... bootstrapMethodArguments) { 68 this.name = name; 69 this.descriptor = descriptor; 70 this.bootstrapMethod = bootstrapMethod; 71 this.bootstrapMethodArguments = bootstrapMethodArguments; 72 } 73 74 /** 75 * Returns the name of this constant. 76 * 77 * @return the name of this constant. 78 */ getName()79 public String getName() { 80 return name; 81 } 82 83 /** 84 * Returns the type of this constant. 85 * 86 * @return the type of this constant, as a field descriptor. 87 */ getDescriptor()88 public String getDescriptor() { 89 return descriptor; 90 } 91 92 /** 93 * Returns the bootstrap method used to compute the value of this constant. 94 * 95 * @return the bootstrap method used to compute the value of this constant. 96 */ getBootstrapMethod()97 public Handle getBootstrapMethod() { 98 return bootstrapMethod; 99 } 100 101 /** 102 * Returns the number of arguments passed to the bootstrap method, in order to compute the value 103 * of this constant. 104 * 105 * @return the number of arguments passed to the bootstrap method, in order to compute the value 106 * of this constant. 107 */ getBootstrapMethodArgumentCount()108 public int getBootstrapMethodArgumentCount() { 109 return bootstrapMethodArguments.length; 110 } 111 112 /** 113 * Returns an argument passed to the bootstrap method, in order to compute the value of this 114 * constant. 115 * 116 * @param index an argument index, between 0 and {@link #getBootstrapMethodArgumentCount()} 117 * (exclusive). 118 * @return the argument passed to the bootstrap method, with the given index. 119 */ getBootstrapMethodArgument(final int index)120 public Object getBootstrapMethodArgument(final int index) { 121 return bootstrapMethodArguments[index]; 122 } 123 124 /** 125 * Returns the arguments to pass to the bootstrap method, in order to compute the value of this 126 * constant. WARNING: this array must not be modified, and must not be returned to the user. 127 * 128 * @return the arguments to pass to the bootstrap method, in order to compute the value of this 129 * constant. 130 */ getBootstrapMethodArgumentsUnsafe()131 Object[] getBootstrapMethodArgumentsUnsafe() { 132 return bootstrapMethodArguments; 133 } 134 135 /** 136 * Returns the size of this constant. 137 * 138 * @return the size of this constant, i.e., 2 for {@code long} and {@code double}, 1 otherwise. 139 */ getSize()140 public int getSize() { 141 char firstCharOfDescriptor = descriptor.charAt(0); 142 return (firstCharOfDescriptor == 'J' || firstCharOfDescriptor == 'D') ? 2 : 1; 143 } 144 145 @Override equals(final Object object)146 public boolean equals(final Object object) { 147 if (object == this) { 148 return true; 149 } 150 if (!(object instanceof ConstantDynamic)) { 151 return false; 152 } 153 ConstantDynamic constantDynamic = (ConstantDynamic) object; 154 return name.equals(constantDynamic.name) 155 && descriptor.equals(constantDynamic.descriptor) 156 && bootstrapMethod.equals(constantDynamic.bootstrapMethod) 157 && Arrays.equals(bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments); 158 } 159 160 @Override hashCode()161 public int hashCode() { 162 return name.hashCode() 163 ^ Integer.rotateLeft(descriptor.hashCode(), 8) 164 ^ Integer.rotateLeft(bootstrapMethod.hashCode(), 16) 165 ^ Integer.rotateLeft(Arrays.hashCode(bootstrapMethodArguments), 24); 166 } 167 168 @Override toString()169 public String toString() { 170 return name 171 + " : " 172 + descriptor 173 + ' ' 174 + bootstrapMethod 175 + ' ' 176 + Arrays.toString(bootstrapMethodArguments); 177 } 178 } 179