Commit 2152b6ab authored by Eric Bruneton's avatar Eric Bruneton

Merge branch 'ASM7_CONDY'

parents 9d468c94 a3a7c2fb
......@@ -29,6 +29,7 @@ package org.objectweb.asm.tree.analysis;
import java.util.List;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
......@@ -155,6 +156,8 @@ public class BasicInterpreter extends Interpreter<BasicValue> implements Opcodes
}
} else if (value instanceof Handle) {
return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
} else if (value instanceof ConstantDynamic) {
return newValue(Type.getType(((ConstantDynamic)value).getDescriptor()));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
......
......@@ -90,7 +90,7 @@ public class BasicInterpreterTest extends AsmTest {
for (MethodNode methodNode : classNode.methods) {
Analyzer<BasicValue> analyzer =
new Analyzer<BasicValue>(
new BasicInterpreter(Opcodes.ASM6) {
new BasicInterpreter(Opcodes.ASM7_EXPERIMENTAL) {
@Override
public BasicValue merge(final BasicValue value1, final BasicValue value2) {
return new BasicValue(super.merge(value1, value2).getType());
......
......@@ -478,7 +478,7 @@ public class SimpleVerifierTest extends AsmTest implements Opcodes {
Type baseType = Type.getObjectType("C");
Type superType = Type.getObjectType("D");
Type interfaceType = Type.getObjectType("I");
new SimpleVerifier(ASM6, baseType, superType, Arrays.asList(interfaceType), false) {
new SimpleVerifier(ASM7_EXPERIMENTAL, baseType, superType, Arrays.asList(interfaceType), false) {
void test() {
assertTrue(isAssignableFrom(baseType, baseType));
......@@ -496,7 +496,7 @@ public class SimpleVerifierTest extends AsmTest implements Opcodes {
}
}.test();
new SimpleVerifier(ASM6, interfaceType, null, null, true) {
new SimpleVerifier(ASM7_EXPERIMENTAL, interfaceType, null, null, true) {
void test() {
assertTrue(isAssignableFrom(interfaceType, baseType));
......
......@@ -32,6 +32,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -409,6 +410,8 @@ public class AnalyzerAdapter extends MethodVisitor {
}
} else if (value instanceof Handle) {
push("java/lang/invoke/MethodHandle");
} else if (value instanceof ConstantDynamic) {
pushDescriptor(((ConstantDynamic) value).getDescriptor());
} else {
throw new IllegalArgumentException();
}
......
......@@ -28,6 +28,7 @@
package org.objectweb.asm.commons;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -638,6 +639,9 @@ public class InstructionAdapter extends MethodVisitor {
|| (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
throw new UnsupportedOperationException();
}
if (api != Opcodes.ASM7_EXPERIMENTAL && value instanceof ConstantDynamic) {
throw new UnsupportedOperationException();
}
if (value instanceof Integer) {
iconst((Integer) value);
} else if (value instanceof Byte) {
......@@ -660,6 +664,8 @@ public class InstructionAdapter extends MethodVisitor {
tconst((Type) value);
} else if (value instanceof Handle) {
hconst((Handle) value);
} else if (value instanceof ConstantDynamic) {
cconst((ConstantDynamic) value);
} else {
throw new IllegalArgumentException();
}
......@@ -746,6 +752,10 @@ public class InstructionAdapter extends MethodVisitor {
mv.visitLdcInsn(handle);
}
public void cconst(final ConstantDynamic constantDynamic) {
mv.visitLdcInsn(constantDynamic);
}
public void load(final int var, final Type type) {
mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
}
......
......@@ -111,7 +111,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
* @param methodVisitor the method visitor to send the resulting inlined method code to, or <code>
* null</code>.
* @param access the method's access flags.
* @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
* the method is synthetic and/or deprecated.
* @param name the method's name.
* @param descriptor the method's descriptor.
* @param signature the method's signature. May be <tt>null</tt>.
......
......@@ -807,7 +807,7 @@ public class GeneratorAdapterTest {
textifier = new Textifier();
generatorAdapter =
new GeneratorAdapter(
Opcodes.ASM6, new TraceMethodVisitor(textifier), access, name, descriptor);
Opcodes.ASM7_EXPERIMENTAL, new TraceMethodVisitor(textifier), access, name, descriptor);
}
public String push(final boolean value) {
......
......@@ -141,7 +141,7 @@ public class LocalVariablesSorterTest extends AsmTest {
new ClassReader(new FileInputStream("src/test/resources/Issue317586.class"));
ClassWriter classWriter = new ClassWriter(0);
ClassVisitor classVisitor =
new ClassVisitor(Opcodes.ASM6, classWriter) {
new ClassVisitor(Opcodes.ASM7_EXPERIMENTAL, classWriter) {
@Override
public MethodVisitor visitMethod(
final int access,
......
......@@ -129,6 +129,7 @@ public abstract class AsmTest {
JDK8_INNER_CLASS("jdk8.AllStructures$InnerClass"),
JDK8_LARGE_METHOD("jdk8.LargeMethod"),
JDK9_MODULE("jdk9.module-info"),
JDK11_ALL_INSTRUCTIONS("jdk11.AllInstructions"),
JDK11_ALL_STRUCTURES("jdk11.AllStructures"),
JDK11_ALL_STRUCTURES_NESTED("jdk11.AllStructures$Nested");
......
......@@ -237,6 +237,8 @@ class ClassDump {
return new ConstantMethodHandleInfo(parser, classContext);
case 16:
return new ConstantMethodTypeInfo(parser, classContext);
case 17:
return new ConstantDynamicInfo(parser, classContext);
case 18:
return new ConstantInvokeDynamicInfo(parser, classContext);
case 19:
......@@ -731,6 +733,37 @@ class ClassDump {
}
}
/**
* A CONSTANT_Dynamic_info item.
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.13">JVMS
* 4.4.13</a>
*/
private static class ConstantDynamicInfo extends CpInfo {
private final int bootstrapMethodAttrIndex;
private final int nameAndTypeIndex;
/**
* Parses a CONSTANT_Dynamic_info item.
*
* @param parser a class parser.
* @param classContext a context to lookup constant pool items from their index.
* @throws IOException if the class can't be parsed.
*/
ConstantDynamicInfo(final Parser parser, final ClassContext classContext) throws IOException {
super(classContext);
this.bootstrapMethodAttrIndex = parser.u2();
this.nameAndTypeIndex = parser.u2();
}
@Override
String dump() {
return bootstrapMethodAttrIndex
+ "."
+ getCpInfo(nameAndTypeIndex, ConstantNameAndTypeInfo.class).dump();
}
}
/**
* Parses and dumps a field_info structure.
*
......
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, France Telecom
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
package jdk11;
import java.io.FileOutputStream;
import java.io.IOException;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* Generates classes with all the JDK11 specific instructions.
*
* <p>TODO: remove this and use the JDK11 to compile equivalent classes, when it is released.
*
* @author Eric Bruneton
*/
public class DumpAllInstructions implements Opcodes {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("AllInstructions.class");
fileOutputStream.write(dumpAllInstructions());
fileOutputStream.close();
}
private static byte[] dumpAllInstructions() {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
classWriter.visit(
V11, ACC_PUBLIC + ACC_SUPER, "jdk11/AllInstructions", null, "java/lang/Object", null);
addDefaultConstructor(classWriter);
MethodVisitor methodVisitor =
classWriter.visitMethod(ACC_PUBLIC, "m", "()Ljava/lang/Object;", null, null);
methodVisitor.visitCode();
methodVisitor.visitLdcInsn(
new ConstandDynamic(
"name",
"Ljava/lang/Object;",
new Handle(
H_INVOKESTATIC,
"HandleOwner",
"handleField",
"(Ljava/lang/Object;)Ljava/lang/Object;",
false),
new ConstantDynamic(
"argumentName",
"Ljava/lang/Object;",
new Handle(
H_GETSTATIC,
"ArgumentHandleOwner",
"argumentHandleName",
"Ljava/lang/Object;",
false))));
methodVisitor.visitInsn(ARETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
classWriter.visitEnd();
return classWriter.toByteArray();
}
private static void addDefaultConstructor(final ClassWriter classWriter) {
MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
}
}
......@@ -33,6 +33,7 @@ import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -659,6 +660,17 @@ public class MethodNode extends MethodVisitor {
throw new UnsupportedClassVersionException();
}
}
if (api != Opcodes.ASM7_EXPERIMENTAL) {
for (int i = instructions.size() - 1; i >= 0; --i) {
AbstractInsnNode insn = instructions.get(i);
if (insn instanceof LdcInsnNode) {
Object value = ((LdcInsnNode) insn).cst;
if (value instanceof ConstantDynamic) {
throw new UnsupportedClassVersionException();
}
}
}
}
}
/**
......
......@@ -81,9 +81,9 @@ public class ClassNodeTest extends AsmTest implements Opcodes {
assertEquals("1.0", moduleNode.version);
ModuleNode otherModuleNode =
new ModuleNode(Opcodes.ASM6, "otherModule", 456, "2.0", null, null, null, null, null);
new ModuleNode(Opcodes.ASM7_EXPERIMENTAL, "otherModule", 456, "2.0", null, null, null, null, null);
moduleNode.accept(
new ClassVisitor(Opcodes.ASM6) {
new ClassVisitor(Opcodes.ASM7_EXPERIMENTAL) {
@Override
public ModuleVisitor visitModule(
final String name, final int access, final String version) {
......@@ -150,7 +150,7 @@ public class ClassNodeTest extends AsmTest implements Opcodes {
assertEquals("value", annotationNode.values.get(17));
annotationNode.accept(
new AnnotationVisitor(Opcodes.ASM6) {
new AnnotationVisitor(Opcodes.ASM7_EXPERIMENTAL) {
@Override
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
......
......@@ -721,7 +721,7 @@ public class InsnListTest {
final InsnList insnList = new InsnList();
list1.accept(
new MethodVisitor(Opcodes.ASM6) {
new MethodVisitor(Opcodes.ASM7_EXPERIMENTAL) {
@Override
public void visitInsn(final int opcode) {
insnList.add(new InsnNode(opcode));
......
......@@ -33,6 +33,7 @@ import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
......@@ -163,6 +164,7 @@ public class ASMifier extends Printer {
text.add("import org.objectweb.asm.Attribute;\n");
text.add("import org.objectweb.asm.ClassReader;\n");
text.add("import org.objectweb.asm.ClassWriter;\n");
text.add("import org.objectweb.asm.ConstantDynamic;\n");
text.add("import org.objectweb.asm.FieldVisitor;\n");
text.add("import org.objectweb.asm.Handle;\n");
text.add("import org.objectweb.asm.Label;\n");
......@@ -1378,6 +1380,21 @@ public class ASMifier extends Printer {
stringBuilder.append(handle.getName()).append("\", \"");
stringBuilder.append(handle.getDesc()).append("\", ");
stringBuilder.append(handle.isInterface()).append(")");
} else if (value instanceof ConstantDynamic) {
stringBuilder.append("new ConstantDynamic(\"");
ConstantDynamic constantDynamic = (ConstantDynamic) value;
stringBuilder.append(constantDynamic.getName()).append("\", \"");
stringBuilder.append(constantDynamic.getDescriptor()).append("\", ");
appendConstant(constantDynamic.getBootstrapMethod());
stringBuilder.append(", new Object[] {");
Object[] bootstrapMethodArguments = constantDynamic.getBootstrapMethodArguments();
for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
appendConstant(bootstrapMethodArguments[i]);
if (i != bootstrapMethodArguments.length - 1) {
stringBuilder.append(", ");
}
}
stringBuilder.append("})");
} else if (value instanceof Byte) {
stringBuilder.append("new Byte((byte)").append(value).append(')');
} else if (value instanceof Boolean) {
......
......@@ -38,6 +38,7 @@ import java.util.Set;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -775,8 +776,8 @@ public class CheckMethodAdapter extends MethodVisitor {
&& bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
throw new IllegalArgumentException("invalid handle tag " + bootstrapMethodHandle.getTag());
}
for (int i = 0; i < bootstrapMethodArguments.length; i++) {
checkLdcConstant(bootstrapMethodArguments[i]);
for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
checkLdcConstant(bootstrapMethodArgument);
}
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
++insnCount;
......@@ -1184,12 +1185,31 @@ public class CheckMethodAdapter extends MethodVisitor {
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a handle requires at least version 1.7");
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
int tag = ((Handle) value).getTag();
Handle handle = (Handle) value;
int tag = handle.getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
checkInternalName(this.version, handle.getOwner(), "handle owner");
if (tag <= Opcodes.H_PUTSTATIC) {
checkDescriptor(this.version, handle.getDesc(), false);
} else {
checkMethodDescriptor(this.version, handle.getDesc());
}
checkMethodIdentifier(this.version, handle.getName(), "handle name");
} else if (value instanceof ConstantDynamic) {
if ((version & 0xFFFF) < Opcodes.V11) {
throw new IllegalArgumentException("ldc of a ConstantDynamic requires at least version 11");
}
ConstantDynamic constantDynamic = (ConstantDynamic) value;
checkMethodIdentifier(this.version, constantDynamic.getName(), "constant dynamic name");
checkDescriptor(this.version, constantDynamic.getDescriptor(), false);
checkLdcConstant(constantDynamic.getBootstrapMethod());
for (Object bootstrapArgument : constantDynamic.getBootstrapMethodArguments()) {
checkLdcConstant(bootstrapArgument);
}
} else {
checkConstant(value);
}
......
......@@ -35,9 +35,11 @@ import java.util.List;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.TypePath;
/**
......@@ -966,9 +968,10 @@ public abstract class Printer {
*
* @param value the constant to be loaded on the stack. This parameter must be a non null {@link
* Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link
* org.objectweb.asm.Type} of OBJECT or ARRAY sort for <tt>.class</tt> constants, for classes
* whose version is 49.0, a {@link org.objectweb.asm.Type} of METHOD sort or a {@link Handle}
* for MethodType and MethodHandle constants, for classes whose version is 51.0.
* Type} of OBJECT or ARRAY sort for <tt>.class</tt> constants, for classes whose version is
* 49, a {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle
* constants, for classes whose version is 51 or a {@link ConstantDynamic} for a constant
* dynamic for classes whose version is 55.
*/
public abstract void visitLdcInsn(Object value);
......
......@@ -56,7 +56,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor {
* @param printer the printer to convert the visited annotation into text.
*/
public TraceAnnotationVisitor(final AnnotationVisitor annotationVisitor, final Printer printer) {
super(Opcodes.ASM6, annotationVisitor);
super(Opcodes.ASM7_EXPERIMENTAL, annotationVisitor);
this.printer = printer;
}
......
......@@ -254,7 +254,7 @@ public class CheckMethodAdapterTest extends AsmTest implements Opcodes {
ClassReader classReader = new ClassReader("java.lang.Object");
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor =
new ClassVisitor(Opcodes.ASM6, classWriter) {
new ClassVisitor(Opcodes.ASM7_EXPERIMENTAL, classWriter) {
@Override
public MethodVisitor visitMethod(
final int access,
......@@ -267,7 +267,7 @@ public class CheckMethodAdapterTest extends AsmTest implements Opcodes {
if (next == null) {
return next;
}
return new MethodVisitor(Opcodes.ASM6, new CheckMethodAdapter(next)) {
return new MethodVisitor(api, new CheckMethodAdapter(next)) {
private Label entryLabel = null;
......
// class version 55.0 (55)
// access flags 0x21
public class jdk11/AllInstructions {
// access flags 0x1
public <init>()V
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public m()Ljava/lang/Object;
LDC name : Ljava/lang/Object; HandleOwner.handleField(Ljava/lang/Object;)Ljava/lang/Object; (6) [argumentName : Ljava/lang/Object; ArgumentHandleOwner.argumentHandleNameLjava/lang/Object; (2) []]
ARETURN
MAXSTACK = 1
MAXLOCALS = 1
}
......@@ -817,6 +817,27 @@ public class ClassWriter extends ClassVisitor {
return symbolTable.addConstantMethodHandle(tag, owner, name, descriptor, isInterface).index;
}
/**
* Adds a dynamic constant reference to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item. <i>This method is intended for {@link
* Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
*
* @param name name of the invoked method.
* @param descriptor field descriptor of the constant type.
* @param bootstrapMethodHandle the bootstrap method.
* @param bootstrapMethodArguments the bootstrap method constant arguments.
* @return the index of a new or already existing dynamic constant reference item.
*/
public int newConstantDynamic(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
return symbolTable.addConstantDynamic(
name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)
.index;
}
/**
* Adds an invokedynamic reference to the constant pool of the class being build. Does nothing if
* the constant pool already contains a similar item. <i>This method is intended for {@link
......
// ASM: a very small and fast Java bytecode manipulation framework
// Copyright (c) 2000-2011 INRIA, France Telecom
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
package org.objectweb.asm;
import java.util.Arrays;
/**
* A constant whose value is computed at runtime, with a bootstrap method.
*
* @author Remi Forax
* @deprecated This API is experimental.
*/
@Deprecated
public final class ConstantDynamic {
/** The constant name (can be arbitrary). */
private final String name;
/** The constant type (must be a field descriptor). */
private final String descriptor;
/** The bootstrap method to use to compute the constant value at runtime. */
private final Handle bootstrapMethod;
/**
* The arguments to pass to the bootstrap method, in order to compute the constant value at
* runtime.
*/
private final Object[] bootstrapMethodArguments;
/**
* Constructs a new {@link ConstantDynamic}.
*
* @param name the constant name (can be arbitrary).
* @param descriptor the constant type (must be a field descriptor).
* @param bootstrapMethod the bootstrap method to use to compute the constant value at runtime.
* @param bootstrapMethodArguments the arguments to pass to the bootstrap method, in order to
* compute the constant value at runtime.
*/
public ConstantDynamic(
final String name,
final String descriptor,
final Handle bootstrapMethod,
final Object... bootstrapMethodArguments) {
this.name = name;
this.descriptor = descriptor;
this.bootstrapMethod = bootstrapMethod;
this.bootstrapMethodArguments = bootstrapMethodArguments;
}
/**
* Returns the name of this constant.
*
* @return the name of this constant.
*/
public String getName() {
return name;
}
/**
* Returns the type of this constant.
*
* @return the type of this constant, as a field descriptor.
*/
public String getDescriptor() {
return descriptor;
}
/**
* Returns the bootstrap method used to compute the value of this constant.
*
* @return the bootstrap method used to compute the value of this constant.
*/
public Handle getBootstrapMethod() {
return bootstrapMethod;
}
/**
* Returns the arguments to pass to the bootstrap method, in order to compute the value of this
* constant.
*
* @return the arguments to pass to the bootstrap method, in order to compute the value of this
* constant.
*/
public Object[] getBootstrapMethodArguments() {
return bootstrapMethodArguments;
}
@Override
public boolean equals(final Object object) {
if (object == this) {
return true;
}
if (!(object instanceof ConstantDynamic)) {
return false;
}
ConstantDynamic constantDynamic = (ConstantDynamic) object;
return name.equals(constantDynamic.name)
&& descriptor.equals(constantDynamic.descriptor)
&& bootstrapMethod.equals(constantDynamic.bootstrapMethod)
&& Arrays.equals(bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments);
}
@Override
public int hashCode() {
return name.hashCode()
^ Integer.rotateLeft(descriptor.hashCode(), 8)
^ Integer.rotateLeft(bootstrapMethod.hashCode(), 16)
^ Integer.rotateLeft(Arrays.hashCode(bootstrapMethodArguments), 24);
}
@Override
public String toString() {
return name
+ " : "
+ descriptor
+ ' '
+ bootstrapMethod
+ ' '