下面列出了org.objectweb.asm.Opcodes# V1_7 ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
void checkLDCConstant(final Object cst) {
if (cst instanceof Type) {
int s = ((Type) cst).getSort();
if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (cst instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a handle requires at least version 1.7");
}
int tag = ((Handle) cst).getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
} else {
checkConstant(cst);
}
}
@Override
public void visit(
int version,
int access,
String name,
String signature,
String superName,
String[] interfaces) {
internalName = name;
this.access = access;
this.signature = signature;
this.superName = superName;
this.interfaces = interfaces;
isInterface = BitFlags.isSet(access, Opcodes.ACC_INTERFACE);
// ASM uses the high 16 bits for the minor version:
// https://asm.ow2.io/javadoc/org/objectweb/asm/ClassVisitor.html#visit-int-int-java.lang.String-java.lang.String-java.lang.String-java.lang.String:A-
// See https://github.com/bazelbuild/bazel/issues/6299 for an example of a class file with a
// non-zero minor version.
int major = version & 0xffff;
if (major > Opcodes.V1_7) {
version = Opcodes.V1_7;
}
super.visit(version, access, name, signature, superName, interfaces);
}
/** Gets the class file version corresponding to the given source version constant. */
public static int sourceVersionToClassFileVersion(SourceVersion version) {
switch (version) {
case RELEASE_0:
return Opcodes.V1_1; // JVMS8 4.1: 1.0 and 1.1 both support version 45.3 (Opcodes.V1_1)
case RELEASE_1:
return Opcodes.V1_1;
case RELEASE_2:
return Opcodes.V1_2;
case RELEASE_3:
return Opcodes.V1_3;
case RELEASE_4:
return Opcodes.V1_4;
case RELEASE_5:
return Opcodes.V1_5;
case RELEASE_6:
return Opcodes.V1_6;
case RELEASE_7:
return Opcodes.V1_7;
case RELEASE_8:
return Opcodes.V1_8;
default:
throw new IllegalArgumentException(String.format("Unexpected source version: %s", version));
}
}
protected int computeFlag(ClassReader classReader) {
int flag = ClassWriter.COMPUTE_MAXS;
//如果低于1.7版本,还是用compute maxs吧
short version = classReader.readShort(6);
if (version >= Opcodes.V1_7) {
flag = ClassWriter.COMPUTE_FRAMES;
}
return flag;
}
private MethodNode makeBase(String name, String desc) {
ClassNode owner = new ClassNode();
owner.node.version = Opcodes.V1_7;
owner.node.name = name;
owner.node.superName = "java/lang/Object";
owner.node.access = Opcodes.ACC_PUBLIC;
MethodNode m = new MethodNode(new org.objectweb.asm.tree.MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "eval", desc, null, null), owner);
owner.addMethod(m);
return m;
}
private static int chooseBytecodeVersion(final boolean invokedynamic, final boolean previewFeatures, final String targetBytecode) {
Integer bytecodeVersion = CompilerConfiguration.JDK_TO_BYTECODE_VERSION_MAP.get(targetBytecode);
if (bytecodeVersion == null) {
throw new GroovyBugError("Bytecode version [" + targetBytecode + "] is not supported by the compiler");
}
if (invokedynamic && bytecodeVersion <= Opcodes.V1_7) {
return Opcodes.V1_7; // invokedynamic added here
} else if (previewFeatures) {
return bytecodeVersion | Opcodes.V_PREVIEW;
} else {
return bytecodeVersion;
}
}
protected void parseClassVersion() throws Exception {
String noMatchError = "Found no class version at beginning of class!";
String value;
if(!nextToken().equals("//"))
throw new Exception(noMatchError);
if(!nextToken().equals("class"))
throw new Exception(noMatchError);
if(!nextToken().equals("version"))
throw new Exception(noMatchError);
value = nextToken();
int version = (int)Float.parseFloat(value);
switch (version) {
case 50:
classVersion = Opcodes.V1_6;
System.out.println("V1_6");
break;
case 51:
classVersion = Opcodes.V1_7;
break;
case 52:
classVersion = Opcodes.V1_8;
break;
default:
throw new Exception("Unsuported class version: " + version);
}
//Move to next line and Verify
nextToken();
value = nextToken();
if(!value.equals("\n"))
throw new Exception("Error while parsing class version, expected \n, got: " + value);
}
/** Gets the class file version corresponding to the given source version constant. */
public static int sourceVersionToClassFileVersion(SourceVersion version) {
switch (version) {
case RELEASE_0:
return Opcodes.V1_1; // JVMS8 4.1: 1.0 and 1.1 both support version 45.3 (Opcodes.V1_1)
case RELEASE_1:
return Opcodes.V1_1;
case RELEASE_2:
return Opcodes.V1_2;
case RELEASE_3:
return Opcodes.V1_3;
case RELEASE_4:
return Opcodes.V1_4;
case RELEASE_5:
return Opcodes.V1_5;
case RELEASE_6:
return Opcodes.V1_6;
case RELEASE_7:
return Opcodes.V1_7;
case RELEASE_8:
return Opcodes.V1_8;
case RELEASE_9:
return Opcodes.V9;
case RELEASE_10:
return Opcodes.V10;
case RELEASE_11:
return Opcodes.V11;
default:
throw new IllegalArgumentException(String.format("Unexpected source version: %s", version));
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
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());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "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());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}
@Override
public void visit(final int version, final int access, final String name, final String signature, final String superName,
final String[] interfaces) {
String simpleName;
if (name == null) {
simpleName = "module-info";
} else {
int n = name.lastIndexOf('/');
if (n == -1) {
simpleName = name;
} else {
text.add("package asm." + name.substring(0, n).replace('/', '.') + ";\n");
simpleName = name.substring(n + 1).replace('-', '_');
}
}
text.add("import java.util.*;\n");
text.add("import org.objectweb.asm.*;\n");
text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
text.add("public static byte[] dump () throws Exception {\n\n");
text.add("ClassWriter cw = new ClassWriter(0);\n");
text.add("FieldVisitor fv;\n");
text.add("MethodVisitor mv;\n");
text.add("AnnotationVisitor av0;\n\n");
buf.setLength(0);
buf.append("cw.visit(");
switch (version) {
case Opcodes.V1_1:
buf.append("V1_1");
break;
case Opcodes.V1_2:
buf.append("V1_2");
break;
case Opcodes.V1_3:
buf.append("V1_3");
break;
case Opcodes.V1_4:
buf.append("V1_4");
break;
case Opcodes.V1_5:
buf.append("V1_5");
break;
case Opcodes.V1_6:
buf.append("V1_6");
break;
case Opcodes.V1_7:
buf.append("V1_7");
break;
case Opcodes.V1_8:
buf.append("V1_8");
break;
case Opcodes.V9:
buf.append("V9");
break;
default:
buf.append(version);
break;
}
buf.append(", ");
appendAccess(access | ACCESS_CLASS);
buf.append(", ");
appendConstant(name);
buf.append(", ");
appendConstant(signature);
buf.append(", ");
appendConstant(superName);
buf.append(", ");
if (interfaces != null && interfaces.length > 0) {
buf.append("new String[] {");
for (int i = 0; i < interfaces.length; ++i) {
buf.append(i == 0 ? " " : ", ");
appendConstant(interfaces[i]);
}
buf.append(" }");
} else {
buf.append("null");
}
buf.append(");\n\n");
text.add(buf.toString());
}
/**
* Creates a new ASM backend
* @param sc The SootClass that is to be converted into bytecode
* @param javaVersion A particular Java version enforced by the user, may be 0 for automatic detection, must not be lower than necessary for all features used
*/
public AbstractASMBackend(SootClass sc, int javaVersion) {
this.sc = sc;
int minVersion = getMinJavaVersion(sc);
if (javaVersion == 0)
javaVersion = Options.java_version_default;
if(javaVersion != Options.java_version_default && javaVersion < minVersion){
throw new IllegalArgumentException("Enforced Java version " + translateJavaVersion(javaVersion) + " too low to support required features (" + translateJavaVersion(minVersion) + " required)");
}
javaVersion = Math.max(javaVersion, minVersion);
switch (javaVersion) {
case Options.java_version_1_1:
this.javaVersion = Opcodes.V1_1;
break;
case Options.java_version_1_2:
this.javaVersion = Opcodes.V1_2;
break;
case Options.java_version_1_3:
this.javaVersion = Opcodes.V1_3;
break;
case Options.java_version_1_4:
this.javaVersion = Opcodes.V1_4;
break;
case Options.java_version_1_5:
this.javaVersion = Opcodes.V1_5;
break;
case Options.java_version_1_6:
this.javaVersion = Opcodes.V1_6;
break;
case Options.java_version_1_7:
this.javaVersion = Opcodes.V1_7;
break;
case Options.java_version_1_8:
this.javaVersion = Opcodes.V1_8;
break;
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
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());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "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());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
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());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "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());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}
/**
* J7 and up include support for INVOKEDYNAMIC instructions.
*
* @return true if the wrapped {@link ClassNode} supports INVOKEDYNAMIC instructions.
*/
public boolean allowsIndy() {
return classNode.version >= Opcodes.V1_7 && classNode.version != Opcodes.V1_1;
}