下面列出了org.objectweb.asm.Opcodes# V1_8 ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/** 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));
}
}
@Override
public void visitMethodInsn(
final int opcodeAndSource,
final String owner,
final String name,
final String descriptor,
final boolean isInterface) {
if (api < Opcodes.ASM5 && (opcodeAndSource & Opcodes.SOURCE_DEPRECATED) == 0) {
// Redirect the call to the deprecated version of this method.
super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
return;
}
int opcode = opcodeAndSource & ~Opcodes.SOURCE_MASK;
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkOpcodeMethod(opcode, Method.VISIT_METHOD_INSN);
if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
checkMethodIdentifier(version, name, "name");
}
checkInternalName(version, owner, "owner");
checkMethodDescriptor(version, descriptor);
if (opcode == Opcodes.INVOKEVIRTUAL && isInterface) {
throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
}
if (opcode == Opcodes.INVOKEINTERFACE && !isInterface) {
throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
}
if (opcode == Opcodes.INVOKESPECIAL && isInterface && (version & 0xFFFF) < Opcodes.V1_8) {
throw new IllegalArgumentException(
"INVOKESPECIAL can't be used with interfaces prior to Java 8");
}
super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
++insnCount;
}
static boolean hasDefaultMethods(@NonNull ClassNode classNode) {
if ((classNode.access & Opcodes.ACC_INTERFACE) == 0) {
return false;
}
// interfaces before V1_8 cannot have default methods.
return classNode.version >= Opcodes.V1_8
&& ((List<MethodNode>) classNode.methods)
.stream()
.anyMatch(methodNode -> (methodNode.access & Opcodes.ACC_ABSTRACT) == 0);
}
private void doVisitMethodInsn(int opcode, final String owner, final String name, final String desc, final boolean itf) {
checkStartCode();
checkEndCode();
checkOpcode(opcode, 5);
if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
checkMethodIdentifier(version, name, "name");
}
checkInternalName(owner, "owner");
checkMethodDesc(desc);
if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
}
if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
}
if (opcode == Opcodes.INVOKESPECIAL && itf && (version & 0xFFFF) < Opcodes.V1_8) {
throw new IllegalArgumentException("INVOKESPECIAL can't be used with interfaces prior to Java 8");
}
// Calling super.visitMethodInsn requires to call the correct version
// depending on this.api (otherwise infinite loops can occur). To
// simplify and to make it easier to automatically remove the backward
// compatibility code, we inline the code of the overridden method here.
if (mv != null) {
mv.visitMethodInsn(opcode, owner, name, desc, itf);
}
++insnCount;
}
@Override
public void visit(final int version, final int access, final String name, final String signature, final String superName,
final String[] interfaces) {
super.visit(Opcodes.V1_8, access, name, null, superName, interfaces);
int index = name.lastIndexOf('/');
if (index > 0) {
pkgName = name.substring(0, index);
} else {
pkgName = "";
}
clsName = name;
isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
}
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);
}
private void doVisitMethodInsn(
final int opcode,
final String owner,
final String name,
final String descriptor,
final boolean isInterface) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkOpcodeMethod(opcode, Method.VISIT_METHOD_INSN);
if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
checkMethodIdentifier(version, name, "name");
}
checkInternalName(version, owner, "owner");
checkMethodDescriptor(version, descriptor);
if (opcode == Opcodes.INVOKEVIRTUAL && isInterface) {
throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
}
if (opcode == Opcodes.INVOKEINTERFACE && !isInterface) {
throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
}
if (opcode == Opcodes.INVOKESPECIAL && isInterface && (version & 0xFFFF) < Opcodes.V1_8) {
throw new IllegalArgumentException(
"INVOKESPECIAL can't be used with interfaces prior to Java 8");
}
// Calling super.visitMethodInsn requires to call the correct version depending on this.api
// (otherwise infinite loops can occur). To simplify and to make it easier to automatically
// remove the backward compatibility code, we inline the code of the overridden method here.
if (mv != null) {
mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
++insnCount;
}
private void doVisitMethodInsn(
final int opcode,
final String owner,
final String name,
final String descriptor,
final boolean isInterface) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkOpcodeMethod(opcode, Method.VISIT_METHOD_INSN);
if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
checkMethodIdentifier(version, name, "name");
}
checkInternalName(version, owner, "owner");
checkMethodDescriptor(version, descriptor);
if (opcode == Opcodes.INVOKEVIRTUAL && isInterface) {
throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
}
if (opcode == Opcodes.INVOKEINTERFACE && !isInterface) {
throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
}
if (opcode == Opcodes.INVOKESPECIAL && isInterface && (version & 0xFFFF) < Opcodes.V1_8) {
throw new IllegalArgumentException(
"INVOKESPECIAL can't be used with interfaces prior to Java 8");
}
// Calling super.visitMethodInsn requires to call the correct version depending on this.api
// (otherwise infinite loops can occur). To simplify and to make it easier to automatically
// remove the backward compatibility code, we inline the code of the overridden method here.
if (mv != null) {
mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
++insnCount;
}
/** 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));
}
}
public ClassCode(ClassNode classNode) {
version = classNode.version;
access = classNode.access;
name = classNode.name;
signature = classNode.signature;
superName = classNode.superName;
interfaces = ListUtils.emptyIfNull(classNode.interfaces);
sourceFile = classNode.sourceFile;
sourceDebug = classNode.sourceDebug;
module = classNode.module;
outerClass = classNode.outerClass;
outerMethod = classNode.outerMethod;
outerMethodDesc = classNode.outerMethodDesc;
visibleAnnotations = ListUtils.emptyIfNull(classNode.visibleAnnotations);
invisibleAnnotations = ListUtils.emptyIfNull(classNode.invisibleAnnotations);
visibleTypeAnnotations = ListUtils.emptyIfNull(classNode.visibleTypeAnnotations);
invisibleTypeAnnotations = ListUtils.emptyIfNull(classNode.invisibleTypeAnnotations);
attrs = ListUtils.emptyIfNull(classNode.attrs);
innerClasses = ListUtils.emptyIfNull(classNode.innerClasses);
nestHostClass = classNode.nestHostClass;
nestMembers = ListUtils.emptyIfNull(classNode.nestMembers);
//fields = ListUtils.emptyIfNull(classNode.fields);
//methods = ListUtils.emptyIfNull(classNode.methods);
final List<FieldNode> fieldNodes = ListUtils.emptyIfNull(classNode.fields);
fields = new LinkedHashMap<>(hashMapInitialCapacity(fieldNodes.size()));
for (FieldNode fieldNode : fieldNodes) {
final FieldCode fieldCode = new FieldCode(fieldNode);
fields.put(fieldCode.name, fieldCode);
}
final List<MethodNode> methodNodes = ListUtils.emptyIfNull(classNode.methods);
methods = new ArrayList<>(arrayListInitialCapacity(methodNodes.size()));
methodMap = new LinkedHashMap<>(hashMapInitialCapacity(methodNodes.size() * 2));
for (MethodNode methodNode : methodNodes) {
final MethodCode methodCode = new MethodCode(this, methodNode);
methods.add(methodCode);
methodMap.put(methodCode.nameDesc, methodCode);
if (!methodMap.containsKey(methodCode.name)) {
methodMap.put(methodCode.name, methodCode);
}
}
variableType = VariableType.valueOf(name);
isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
isSuper = (access & Opcodes.ACC_SUPER) != 0;
isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
isV1_6 = (version & Opcodes.V1_6) != 0;
isV1_8 = (version & Opcodes.V1_8) != 0;
simpleName = getSimpleName();
}
public ClassCode(ClassNode classNode) {
version = classNode.version;
access = classNode.access;
name = classNode.name;
signature = classNode.signature;
superName = classNode.superName;
interfaces = ListUtils.emptyIfNull(classNode.interfaces);
sourceFile = classNode.sourceFile;
sourceDebug = classNode.sourceDebug;
module = classNode.module;
outerClass = classNode.outerClass;
outerMethod = classNode.outerMethod;
outerMethodDesc = classNode.outerMethodDesc;
visibleAnnotations = ListUtils.emptyIfNull(classNode.visibleAnnotations);
invisibleAnnotations = ListUtils.emptyIfNull(classNode.invisibleAnnotations);
visibleTypeAnnotations = ListUtils.emptyIfNull(classNode.visibleTypeAnnotations);
invisibleTypeAnnotations = ListUtils.emptyIfNull(classNode.invisibleTypeAnnotations);
attrs = ListUtils.emptyIfNull(classNode.attrs);
innerClasses = ListUtils.emptyIfNull(classNode.innerClasses);
nestHostClassExperimental = classNode.nestHostClassExperimental;
nestMembersExperimental = ListUtils.emptyIfNull(classNode.nestMembersExperimental);
//fields = ListUtils.emptyIfNull(classNode.fields);
//methods = ListUtils.emptyIfNull(classNode.methods);
final List<FieldNode> fieldNodes = ListUtils.emptyIfNull(classNode.fields);
fields = new LinkedHashMap<>(hashMapInitialCapacity(fieldNodes.size()));
for (FieldNode fieldNode : fieldNodes) {
final FieldCode fieldCode = new FieldCode(fieldNode);
fields.put(fieldCode.name, fieldCode);
}
final List<MethodNode> methodNodes = ListUtils.emptyIfNull(classNode.methods);
methods = new ArrayList<>(arrayListInitialCapacity(methodNodes.size()));
methodMap = new LinkedHashMap<>(hashMapInitialCapacity(methodNodes.size() * 2));
for (MethodNode methodNode : methodNodes) {
final MethodCode methodCode = new MethodCode(this, methodNode);
methods.add(methodCode);
methodMap.put(methodCode.nameDesc, methodCode);
if (!methodMap.containsKey(methodCode.name)) {
methodMap.put(methodCode.name, methodCode);
}
}
variableType = VariableType.valueOf(name);
isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
isSuper = (access & Opcodes.ACC_SUPER) != 0;
isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
isV1_6 = (version & Opcodes.V1_6) != 0;
isV1_8 = (version & Opcodes.V1_8) != 0;
simpleName = getSimpleName();
}
@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;
}
}
@Override
public Void visitType(TypeElement e, ClassVisitor visitor) {
if (classVisitorStarted) {
// We'll get inner class references later
return null;
}
TypeMirror superclass = e.getSuperclass();
if (superclass.getKind() == TypeKind.NONE) {
superclass = Objects.requireNonNull(elements.getTypeElement("java.lang.Object")).asType();
}
int classFileVersion = SourceVersionUtils.sourceVersionToClassFileVersion(targetVersion);
visitor.visit(
classFileVersion,
accessFlagsUtils.getAccessFlagsForClassNode(e),
descriptorFactory.getInternalName(e),
signatureFactory.getSignature(e),
descriptorFactory.getInternalName(superclass),
e.getInterfaces().stream()
.map(descriptorFactory::getInternalName)
.toArray(size -> new String[size]));
classVisitorStarted = true;
// Handle nests in Java 11+. See JEP 181 (https://openjdk.java.net/jeps/181) for details.
if (classFileVersion >= Opcodes.V11) {
if (e.getNestingKind().isNested()) {
visitNestHost(e, visitor);
} else {
visitNestMembers(e, visitor);
}
}
visitAnnotations(e, visitor::visitAnnotation);
super.visitType(e, visitor);
InnerClassesTable innerClassesTable =
new InnerClassesTable(descriptorFactory, accessFlagsUtils, e);
if (e.getKind().isClass() || classFileVersion >= Opcodes.V1_8) {
try {
generateBridges(e, visitor, innerClassesTable);
} catch (UnsupportedOperationException | CannotInferException ex) { // NOPMD
// Can't generate bridges in source-only mode
}
}
innerClassesTable.reportInnerClassReferences(visitor);
return null;
}