下面列出了org.objectweb.asm.Type#OBJECT 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
Builder addDependency(Type type) {
switch (type.getSort()) {
case Type.OBJECT:
mObservedDependencies.add(type);
break;
case Type.ARRAY:
addDependency(type.getElementType());
break;
case Type.METHOD:
addDependency(type.getReturnType());
for (Type argumentType : type.getArgumentTypes()) {
addDependency(argumentType);
}
break;
default:
break;
}
return this;
}
@Override
public void toCode(MethodVisitor visitor, BytecodeFrontend assembler) {
for (int i = 0; i < bounds.length; i++) {
bounds[i].toCode(visitor, assembler);
int[] cast = TypeUtils.getPrimitiveCastOpcodes(bounds[i].getType(), Type.INT_TYPE);
for (int a = 0; a < cast.length; a++)
visitor.visitInsn(cast[a]);
}
if (type.getDimensions() != 1) {
visitor.visitMultiANewArrayInsn(type.getDescriptor(), bounds.length);
} else {
Type element = type.getElementType();
if (element.getSort() == Type.OBJECT || element.getSort() == Type.METHOD) {
visitor.visitTypeInsn(Opcodes.ANEWARRAY, element.getInternalName());
} else {
visitor.visitIntInsn(Opcodes.NEWARRAY, TypeUtils.getPrimitiveArrayOpcode(type));
}
}
}
private void pushDefault(Type type) {
switch (type.getSort()) {
case Type.VOID:
break;
case Type.DOUBLE:
mv.visitInsn(DCONST_0);
break;
case Type.LONG:
mv.visitInsn(LCONST_0);
break;
case Type.FLOAT:
mv.visitInsn(FCONST_0);
break;
case Type.OBJECT:
case Type.ARRAY:
mv.visitInsn(ACONST_NULL);
break;
default:
mv.visitInsn(ICONST_0);
break;
}
}
private void checkType(Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
case Type.LONG:
case Type.FLOAT:
case Type.DOUBLE:
case Type.VOID:
return; // Ignore primitive types.
case Type.ARRAY:
checkType(type.getElementType());
return;
case Type.METHOD:
for (Type argumentType : type.getArgumentTypes()) {
checkType(argumentType);
}
checkType(type.getReturnType());
return;
case Type.OBJECT:
checkInternalName(type.getInternalName());
return;
default:
throw new UnsupportedOperationException("Unhandled type: " + type);
}
}
@Override
public BasicValue merge(final BasicValue v, final BasicValue w) {
if (!v.equals(w)) {
Type t = v.getType();
Type u = w.getType();
if (t != null && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
if (u != null && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
if ("Lnull;".equals(t.getDescriptor())) {
return w;
}
if ("Lnull;".equals(u.getDescriptor())) {
return v;
}
if (isAssignableFrom(t, u)) {
return v;
}
if (isAssignableFrom(u, t)) {
return w;
}
// TODO case of array classes of the same dimension
// TODO should we look also for a common super interface?
// problem: there may be several possible common super
// interfaces
do {
if (t == null || isInterface(t)) {
return BasicValue.REFERENCE_VALUE;
}
t = getSuperClass(t);
if (isAssignableFrom(t, u)) {
return newValue(t);
}
} while (true);
}
}
return BasicValue.UNINITIALIZED_VALUE;
}
return v;
}
/**
* Generates the instructions to box the top stack value using Java 5's valueOf() method. This
* value is replaced by its boxed equivalent on top of the stack.
*
* @param type the type of the top stack value.
*/
public void valueOf(final Type type) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return;
}
if (type == Type.VOID_TYPE) {
push((String) null);
} else {
Type boxedType = getBoxedType(type);
invokeStatic(boxedType, new Method("valueOf", boxedType, new Type[] {type}));
}
}
@Override
protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
Type expectedType = expected.getType();
Type type = value.getType();
switch (expectedType.getSort()) {
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
return type.equals(expectedType);
case Type.ARRAY:
case Type.OBJECT:
if (type.equals(NULL_TYPE)) {
return true;
} else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
if (isAssignableFrom(expectedType, type)) {
return true;
} else if (getClass(expectedType).isInterface()) {
// The merge of class or interface types can only yield class types (because it is not
// possible in general to find an unambiguous common super interface, due to multiple
// inheritance). Because of this limitation, we need to relax the subtyping check here
// if 'value' is an interface.
return Object.class.isAssignableFrom(getClass(type));
} else {
return false;
}
} else {
return false;
}
default:
throw new AssertionError();
}
}
/**
* @param i
* @param ignoreNonFound
* @param ref
* @param retType
* @param sigType
* @throws SerianalyzerException
*/
public void foundImprovedReturnType ( Index i, boolean ignoreNonFound, MethodReference ref, Type retType, Type sigType )
throws SerianalyzerException {
MethodReference c = ref.comparable();
this.checkedReturnType.add(c);
if ( "java.lang.Object".equals(sigType.getClassName()) //$NON-NLS-1$
|| ( "java.io.Serializable".equals(sigType.getClassName()) && //$NON-NLS-1$
!"java.lang.Object".equals(retType.getClassName()) ) ) { //$NON-NLS-1$
if ( this.returnTypes.put(c, retType) != null ) {
this.bench.improvedReturnType();
}
return;
}
else if ( sigType.getSort() != Type.OBJECT || sigType.getClassName().endsWith("[]") ) { //$NON-NLS-1$
return;
}
if ( this.returnTypes.containsKey(c) ) {
return;
}
Type moreConcreteType = TypeUtil.getMoreConcreteType(i, ignoreNonFound, retType, sigType);
if ( this.returnTypes.put(c, moreConcreteType) == null ) {
if ( moreConcreteType.equals(retType) && !moreConcreteType.equals(sigType) ) {
this.bench.improvedReturnType();
}
else {
this.bench.nonImprovedReturnType();
}
}
}
static Optional<String> getClassName(Type aType) {
switch (aType.getSort()) {
case Type.ARRAY:
return getClassName(aType.getElementType());
case Type.OBJECT:
return Optional.of(aType.getClassName());
default:
return Optional.empty();
}
}
public static String typeToString(Type type) {
String className = type.getClassName();
if (type.getSort() == Type.OBJECT) {
className = className.substring(className.lastIndexOf('.')+1);
}
return className;
}
private void add(final Type type) {
int t = type.getSort();
if (t == Type.ARRAY) {
add(type.getElementType());
} else if (t == Type.OBJECT) {
addClassName(type.getClassName());
}
}
/**
* Constructs a new local variable of the given type.
*
* @param type the type of the local variable to be created.
* @return the identifier of the newly created local variable.
*/
public int newLocal(final Type type) {
Object localType;
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
localType = Opcodes.INTEGER;
break;
case Type.FLOAT:
localType = Opcodes.FLOAT;
break;
case Type.LONG:
localType = Opcodes.LONG;
break;
case Type.DOUBLE:
localType = Opcodes.DOUBLE;
break;
case Type.ARRAY:
localType = type.getDescriptor();
break;
case Type.OBJECT:
localType = type.getInternalName();
break;
default:
throw new AssertionError();
}
int local = newLocalMapping(type);
setLocalType(local, type);
setFrameLocal(local, localType);
return local;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
// If this is a clinit, capture it into the MethodNode, for later use. Otherwise, pass it on as normal.
MethodVisitor visitor = null;
if (kClinitName.equals(name)) {
this.cachedClinit = new MethodNode(access, name, descriptor, signature, exceptions);
visitor = this.cachedClinit;
} else {
visitor = super.visitMethod(access, name, descriptor, signature, exceptions);
}
return new MethodVisitor(Opcodes.ASM6, visitor) {
@Override
public void visitLdcInsn(Object value) {
if (value instanceof Type && ((Type) value).getSort() == Type.OBJECT) {
// class constants
// This covers both Type.ARRAY and Type.OBJECT; since both cases were visited in UserClassMappingVisitor and renamed
super.visitLdcInsn(value);
super.visitMethodInsn(Opcodes.INVOKESTATIC, Helper.RUNTIME_HELPER_NAME, wrapClassMethodName, wrapClassMethodDescriptor, false);
} else if (value instanceof String) {
// Note that we are moving all strings to the constantClassName, so look up the constant which has this value.
String staticFieldForConstant = ConstantVisitor.this.constantToFieldMap.get(value);
// (we just created this map in StringConstantCollectionVisitor so nothing can be missing).
RuntimeAssertionError.assertTrue(null != staticFieldForConstant);
super.visitFieldInsn(Opcodes.GETSTATIC, ConstantVisitor.this.constantClassName, staticFieldForConstant, postRenameStringDescriptor);
} else {
// Type of METHOD and Handle are for classes with version 49 and 51 respectively, and should not happen
// https://asm.ow2.io/javadoc/org/objectweb/asm/MethodVisitor.html#visitLdcInsn-java.lang.Object-
RuntimeAssertionError.assertTrue(value instanceof Integer || value instanceof Float || value instanceof Long || value instanceof Double);
super.visitLdcInsn(value);
}
}
};
}
@Override
protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
Type expectedType = expected.getType();
Type type = value.getType();
switch (expectedType.getSort()) {
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
return type.equals(expectedType);
case Type.ARRAY:
case Type.OBJECT:
if (type.equals(NULL_TYPE)) {
return true;
} else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
if (isAssignableFrom(expectedType, type)) {
return true;
} else if (getClass(expectedType).isInterface()) {
// The merge of class or interface types can only yield class types (because it is not
// possible in general to find an unambiguous common super interface, due to multiple
// inheritance). Because of this limitation, we need to relax the subtyping check here
// if 'value' is an interface.
return Object.class.isAssignableFrom(getClass(type));
} else {
return false;
}
} else {
return false;
}
default:
throw new AssertionError();
}
}
@Override
public BasicValue newValue(final Type type) {
if (type == null) {
return BasicValue.UNINITIALIZED_VALUE;
}
switch (type.getSort()) {
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return BasicValue.INT_VALUE;
case Type.FLOAT:
return BasicValue.FLOAT_VALUE;
case Type.LONG:
return BasicValue.LONG_VALUE;
case Type.DOUBLE:
return BasicValue.DOUBLE_VALUE;
case Type.ARRAY:
case Type.OBJECT:
return BasicValue.REFERENCE_VALUE;
default:
throw new AssertionError();
}
}
public void emitNewArray(TypeWidget elementType, BytecodeExpression e) {
MethodVisitor mv = getMethodVisitor();
exec(e);
cast(BaseTypeAdapter.INT32, e.getType());
switch (elementType.getJVMType().getSort()) {
case Type.BYTE:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE);
break;
case Type.BOOLEAN:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN);
break;
case Type.SHORT:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_SHORT);
break;
case Type.INT:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_INT);
break;
case Type.CHAR:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_CHAR);
break;
case Type.FLOAT:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_FLOAT);
break;
case Type.LONG:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_LONG);
break;
case Type.DOUBLE:
mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_DOUBLE);
break;
case Type.OBJECT:
mv.visitTypeInsn(Opcodes.ANEWARRAY, elementType.getJVMType().getInternalName());
break;
default:
throw new UnsupportedOperationException("unknown sort for newArray" + elementType.getJVMType());
}
}
public boolean isReference() {
return type != null && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
}
@Override
public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
switch (insn.getOpcode()) {
case ACONST_NULL:
return newValue(NULL_TYPE);
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
return BasicValue.INT_VALUE;
case LCONST_0:
case LCONST_1:
return BasicValue.LONG_VALUE;
case FCONST_0:
case FCONST_1:
case FCONST_2:
return BasicValue.FLOAT_VALUE;
case DCONST_0:
case DCONST_1:
return BasicValue.DOUBLE_VALUE;
case BIPUSH:
case SIPUSH:
return BasicValue.INT_VALUE;
case LDC:
Object value = ((LdcInsnNode) insn).cst;
if (value instanceof Integer) {
return BasicValue.INT_VALUE;
} else if (value instanceof Float) {
return BasicValue.FLOAT_VALUE;
} else if (value instanceof Long) {
return BasicValue.LONG_VALUE;
} else if (value instanceof Double) {
return BasicValue.DOUBLE_VALUE;
} else if (value instanceof String) {
return newValue(Type.getObjectType("java/lang/String"));
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
return newValue(Type.getObjectType("java/lang/Class"));
} else if (sort == Type.METHOD) {
return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
} 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);
}
case JSR:
return BasicValue.RETURNADDRESS_VALUE;
case GETSTATIC:
return newValue(Type.getType(((FieldInsnNode) insn).desc));
case NEW:
return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
default:
throw new AssertionError();
}
}
@Override
public BasicValue merge(final BasicValue value1, final BasicValue value2) {
if (!value1.equals(value2)) {
Type type1 = value1.getType();
Type type2 = value2.getType();
if (type1 != null
&& (type1.getSort() == Type.OBJECT || type1.getSort() == Type.ARRAY)
&& type2 != null
&& (type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY)) {
if (type1.equals(NULL_TYPE)) {
return value2;
}
if (type2.equals(NULL_TYPE)) {
return value1;
}
if (isAssignableFrom(type1, type2)) {
return value1;
}
if (isAssignableFrom(type2, type1)) {
return value2;
}
int numDimensions = 0;
if (type1.getSort() == Type.ARRAY
&& type2.getSort() == Type.ARRAY
&& type1.getDimensions() == type2.getDimensions()
&& type1.getElementType().getSort() == Type.OBJECT
&& type2.getElementType().getSort() == Type.OBJECT) {
numDimensions = type1.getDimensions();
type1 = type1.getElementType();
type2 = type2.getElementType();
}
do {
if (type1 == null || isInterface(type1)) {
return newArrayValue(Type.getObjectType("java/lang/Object"), numDimensions);
}
type1 = getSuperClass(type1);
if (isAssignableFrom(type1, type2)) {
return newArrayValue(type1, numDimensions);
}
} while (true);
}
return BasicValue.UNINITIALIZED_VALUE;
}
return value1;
}
@Override
public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
switch (insn.getOpcode()) {
case ACONST_NULL:
return newValue(NULL_TYPE);
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
return BasicValue.INT_VALUE;
case LCONST_0:
case LCONST_1:
return BasicValue.LONG_VALUE;
case FCONST_0:
case FCONST_1:
case FCONST_2:
return BasicValue.FLOAT_VALUE;
case DCONST_0:
case DCONST_1:
return BasicValue.DOUBLE_VALUE;
case BIPUSH:
case SIPUSH:
return BasicValue.INT_VALUE;
case LDC:
Object value = ((LdcInsnNode) insn).cst;
if (value instanceof Integer) {
return BasicValue.INT_VALUE;
} else if (value instanceof Float) {
return BasicValue.FLOAT_VALUE;
} else if (value instanceof Long) {
return BasicValue.LONG_VALUE;
} else if (value instanceof Double) {
return BasicValue.DOUBLE_VALUE;
} else if (value instanceof String) {
return newValue(Type.getObjectType("java/lang/String"));
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
return newValue(Type.getObjectType("java/lang/Class"));
} else if (sort == Type.METHOD) {
return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
} 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);
}
case JSR:
return BasicValue.RETURNADDRESS_VALUE;
case GETSTATIC:
return newValue(Type.getType(((FieldInsnNode) insn).desc));
case NEW:
return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
default:
throw new AssertionError();
}
}