下面列出了org.objectweb.asm.Opcodes# ACC_SUPER 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Generates and returns the bytecode for an exception class.
*
* @param name The name of the class to generate.
* @param superName The name of the superclass.
* @return The bytecode for the new class.
*/
public static byte[] generateExceptionClass(String name, String superName) {
ClassWriter out = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
// This class only exists to be a type - the superclasses always do everything.
// (common access for all classes we generate - public and "super", meaning post-1.1 invokestatic).
int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER;
// We ignore generics, so null signature.
String signature = null;
// We implement no interfaces.
String[] interfaces = new String[0];
out.visit(CLASS_VERSION, access, name, signature, superName, interfaces);
// Generate the constructors.
populateExceptionConstructors(out, superName);
// Finish this and dump the bytes.
out.visitEnd();
return out.toByteArray();
}
/**
* Turns this class into an override class that can be loaded by our custom class loader:
*<ul>
* <li>Make the class name be OriginalName$starkoverride</li>
* <li>Ensure the class derives from java.lang.Object, no other inheritance</li>
* <li>Ensure the class has a public parameterless constructor that is a noop.</li>
*</ul>
*/
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
super.visit(version, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER,
name + OVERRIDE_SUFFIX, signature, "java/lang/Object",
new String[]{CHANGE_TYPE.getInternalName()});
// if (DEBUG) {
// System.out.println(">>>>>>>> Processing " + name + "<<<<<<<<<<<<<");
// }
visitedClassName = name;
visitedSuperName = superName;
instanceToStaticDescPrefix = "(L" + visitedClassName + ";";
// Create empty constructor
MethodVisitor mv = super
.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC,
"$starkObsolete", "Z", null, null);
}
/**
* Generates and returns the bytecode for a wrapper class.
*
* @param name The name of the class to generate.
* @param superName The name of the superclass.
* @return The bytecode for the new class.
*/
public static byte[] generateWrapperClass(String name, String superName) {
ClassWriter out = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
// This class only exists to be a type - the superclasses always do everything.
// (common access for all classes we generate - public and "super", meaning post-1.1 invokestatic).
int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER;
// We ignore generics, so null signature.
String signature = null;
// We implement no interfaces.
String[] interfaces = new String[0];
out.visit(CLASS_VERSION, access, name, signature, superName, interfaces);
// Generate the singular constructor.
MethodVisitor methodVisitor = out.visitMethod(Opcodes.ACC_PUBLIC, INIT_NAME, ONE_ARG_DESCRIPTOR, null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, INIT_NAME, ONE_ARG_DESCRIPTOR, false);
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(2, 2);
methodVisitor.visitEnd();
// Finish this and dump the bytes.
out.visitEnd();
return out.toByteArray();
}
/**
* Generates and returns the bytecode for a "legacy-style" exception class. That is, the kind which have their own getCause and getException implementations.
* In our implementation, we will strictly wrap the super-class, and append a getException method.
*
* @param name The name of the class to generate.
* @param superName The name of the superclass.
* @return The bytecode for the new class.
*/
public static byte[] generateLegacyExceptionClass(String name, String superName) {
ClassWriter out = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
// This class only exists to be a type - the superclasses always do everything.
// (common access for all classes we generate - public and "super", meaning post-1.1 invokestatic).
int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER;
// We ignore generics, so null signature.
String signature = null;
// We implement no interfaces.
String[] interfaces = new String[0];
out.visit(CLASS_VERSION, access, name, signature, superName, interfaces);
// Generate the constructors.
populateExceptionConstructors(out, superName);
// Generate the getException method.
{
// NOTE: These methods need to exist with the UserClassMappingVisitor.mapMethodName("" prefixes, since the shadow library is post-shadow.
String returnThrowable = "()L" + PackageConstants.kShadowSlashPrefix + "java/lang/Throwable;";
// This method does not require a charge energy call since it's calling avm_getCause and the billing is done there
MethodVisitor methodVisitor = out.visitMethod(Opcodes.ACC_PUBLIC, NamespaceMapper.mapMethodName("getException"), returnThrowable, null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, name, NamespaceMapper.mapMethodName("getCause"), returnThrowable, false);
methodVisitor.visitInsn(Opcodes.ARETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
}
// Finish this and dump the bytes.
out.visitEnd();
return out.toByteArray();
}
public static int transformClassAccessForInstantRun(int access) {
IncrementalVisitor.AccessRight accessRight = IncrementalVisitor.AccessRight.fromNodeAccess(access);
int fixedVisibility = accessRight == IncrementalVisitor.AccessRight.PACKAGE_PRIVATE
? access | Opcodes.ACC_PUBLIC
: access;
// TODO: only do this on KitKat?
return fixedVisibility | Opcodes.ACC_SUPER;
}
private static void readClassIndex(
Map<ClassIndex, File> indexes, InputStream in, File file, boolean allowSuper)
throws IOException {
ClassReader classReader = new ClassReader(in);
String className = ClassNameUtils.replaceSlash(classReader.getClassName());
boolean projectOutput = file.isDirectory();
int access = classReader.getAccess();
boolean isPublic = (Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC;
boolean isProtected = (Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED;
boolean isInterface = (Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE;
boolean isAnnotation = (Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION;
boolean isSuper = false;
if (allowSuper) {
isSuper = (Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER;
}
if (projectOutput || (isPublic || isProtected || isSuper)) {
String pkg = ClassNameUtils.getPackage(className);
boolean onlyClassName = !preloadClassPackages.contains(pkg);
ClassAnalyzeVisitor classAnalyzeVisitor =
new ClassAnalyzeVisitor(className, onlyClassName, false);
classReader.accept(classAnalyzeVisitor, 0);
ClassIndex classIndex = classAnalyzeVisitor.getClassIndex();
if (!classIndex.isAnonymous) {
classIndex.setInterface(isInterface);
classIndex.setAnnotation(isAnnotation);
indexes.put(classIndex, file);
if (!onlyClassName) {
innerCache.putIfAbsent(className, classAnalyzeVisitor.getMembers());
}
}
}
}
/**
* Turns this class into an override class that can be loaded by our custom class loader:
* <ul>
* <li>Make the class name be OriginalName$override</li>
* <li>Ensure the class derives from java.lang.Object, no other inheritance</li></li>
* <li>Ensure the class has a public parameterless constructor that is a noop.</li></li>
* </ul>
*/
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
super.visit(version, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER,
name + OVERRIDE_SUFFIX, signature, "java/lang/Object",
new String[]{CHANGE_TYPE.getInternalName()});
if (DEBUG) {
System.out.println(">>>>>>>> Processing " + name + "<<<<<<<<<<<<<");
}
visitedClassName = name;
visitedSuperName = superName;
instanceToStaticDescPrefix = "(L" + visitedClassName + ";";
// Create empty constructor
MethodVisitor mv = super
.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC,
"$obsolete", "Z", null, null);
}
@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
if(!superName.equals("java/lang/Object"))
{
System.err.println("WARNING: " + name + " already has a super class which will be overwritten: " + superName
+ "\nThis means that some other mod might no longer work properly!");
}
super.visit(version, access+Opcodes.ACC_SUPER, name, signature, EntityObject.class.getName().replace('.', '/'), interfaces);
}
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();
}
static void appendAccess(final int access, final StringBuilder sb) {
if ((access & Opcodes.ACC_PUBLIC) != 0) {
sb.append("public ");
}
if ((access & Opcodes.ACC_PRIVATE) != 0) {
sb.append("private ");
}
if ((access & Opcodes.ACC_PROTECTED) != 0) {
sb.append("protected ");
}
if ((access & Opcodes.ACC_FINAL) != 0) {
if ((access & ACCESS_MODULE) == 0) {
sb.append("final ");
} else {
sb.append("transitive ");
}
}
if ((access & Opcodes.ACC_STATIC) != 0) {
sb.append("static ");
}
if ((access & Opcodes.ACC_SUPER) != 0) {
if ((access & ACCESS_CLASS) == 0) {
if ((access & ACCESS_MODULE_REQUIRES) != 0) {
sb.append("transitive ");
} else {
if ((access & ACCESS_MODULE) == 0) {
sb.append("synchronized ");
} else {
sb.append("open ");
}
}
} else {
sb.append("super ");
}
}
if ((access & Opcodes.ACC_VOLATILE) != 0) {
if ((access & ACCESS_FIELD) == 0) {
sb.append("bridge ");
} else {
if ((access & ACCESS_MODULE_REQUIRES) == 0) {
sb.append("volatile ");
} else {
sb.append("static ");
}
}
}
if ((access & Opcodes.ACC_TRANSIENT) != 0) {
if ((access & ACCESS_FIELD) == 0) {
sb.append("varargs ");
} else {
sb.append("transient ");
}
}
if ((access & Opcodes.ACC_NATIVE) != 0) {
sb.append("native ");
}
if ((access & Opcodes.ACC_STRICT) != 0) {
sb.append("strict ");
}
if ((access & Opcodes.ACC_INTERFACE) != 0) {
sb.append("interface ");
}
if ((access & Opcodes.ACC_ABSTRACT) != 0) {
sb.append("abstract ");
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
sb.append("synthetic ");
}
if ((access & Opcodes.ACC_ANNOTATION) != 0) {
sb.append("annotation ");
}
if ((access & Opcodes.ACC_ENUM) != 0) {
sb.append("enum ");
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
sb.append("deprecated ");
}
if ((access & Opcodes.ACC_MANDATED) != 0) {
if ((access & ACCESS_CLASS) == 0) {
sb.append("module ");
} else {
sb.append("mandated ");
}
}
}
/**
* Utility method to get the access modifiers of a Host
* @param modVal The bitset representation of the Host's modifiers
* @param host The Host (SootClass, SootField or SootMethod) the modifiers are to be retrieved from
* @return A bitset representation of the Host's modifiers in ASM's internal representation
*/
protected static int getModifiers(int modVal, Host host) {
int modifier = 0;
// Retrieve visibility-modifier
if (Modifier.isPublic(modVal)) {
modifier |= Opcodes.ACC_PUBLIC;
} else if (Modifier.isPrivate(modVal)) {
modifier |= Opcodes.ACC_PRIVATE;
} else if (Modifier.isProtected(modVal)) {
modifier |= Opcodes.ACC_PROTECTED;
}
// Retrieve static-modifier
if (Modifier.isStatic(modVal)
&& ((host instanceof SootField) || (host instanceof SootMethod))) {
modifier |= Opcodes.ACC_STATIC;
}
// Retrieve final-modifier
if (Modifier.isFinal(modVal)) {
modifier |= Opcodes.ACC_FINAL;
}
// Retrieve synchronized-modifier
if (Modifier.isSynchronized(modVal) && host instanceof SootMethod) {
modifier |= Opcodes.ACC_SYNCHRONIZED;
}
// Retrieve volatile/bridge-modifier
if (Modifier.isVolatile(modVal) && !(host instanceof SootClass)) {
modifier |= Opcodes.ACC_VOLATILE;
}
// Retrieve transient/varargs-modifier
if (Modifier.isTransient(modVal) && !(host instanceof SootClass)) {
modifier |= Opcodes.ACC_TRANSIENT;
}
// Retrieve native-modifier
if (Modifier.isNative(modVal) && host instanceof SootMethod) {
modifier |= Opcodes.ACC_NATIVE;
}
// Retrieve interface-modifier
if (Modifier.isInterface(modVal) && host instanceof SootClass) {
modifier |= Opcodes.ACC_INTERFACE;
} else if (host instanceof SootClass) {
/*
* For all classes except for interfaces the super-flag should be
* set. See JVM 8-Specification section 4.1, page 72.
*/
modifier |= Opcodes.ACC_SUPER;
}
// Retrieve abstract-modifier
if (Modifier.isAbstract(modVal) && !(host instanceof SootField)) {
modifier |= Opcodes.ACC_ABSTRACT;
}
// Retrieve strictFP-modifier
if (Modifier.isStrictFP(modVal) && host instanceof SootMethod) {
modifier |= Opcodes.ACC_STRICT;
}
/*
* Retrieve synthetic-modifier. Class not present in source-code but
* generated by e.g. compiler TODO Do we need both checks?
*/
if (Modifier.isSynthetic(modVal) || host.hasTag("SyntheticTag")) {
modifier |= Opcodes.ACC_SYNTHETIC;
}
// Retrieve annotation-modifier
if (Modifier.isAnnotation(modVal) && host instanceof SootClass) {
modifier |= Opcodes.ACC_ANNOTATION;
}
// Retrieve enum-modifier
if (Modifier.isEnum(modVal) && !(host instanceof SootMethod)) {
modifier |= Opcodes.ACC_ENUM;
}
return modifier;
}
protected void parseClassHeader() throws Exception {
int access = parseAccessFlags();
if(access == 0)
throw new Exception("Error: Got zero access modifier while parsing class header!");
if(!nextToken().equals("class"))
throw new Exception("Error: Did not find class identifier while parsing class header!");
String className = nextToken();
String superClassName = null;
List<String> impl = new ArrayList<String>();
String value;
//Extending, implementing or done?
boolean implement = false;
while(true)
{
value = nextToken();
if(implement)
{
if(value.equals("{")) //Done reading implements
break;
impl.add(value);
continue;
}
if(value.equals("implements"))
implement = true;
else if(value.equals("extends"))
superClassName = nextToken();
else if(value.equals("{")) //Done reading header info
break;
}
//Write header
/*if(superClassName != null)
{
access += Opcodes.ACC_SUPER;
System.out.println("super access: " + superClassName);
}
else*/
access += Opcodes.ACC_SUPER; //Seems this is always set after Java 1.1?
if(superClassName == null)
superClassName = "java/lang/Object";
System.out.println("Writing class header:"
+ "\nAccess: " + Integer.toHexString(access).toUpperCase()
+ "\nName: " + className
+ "\nSuper class: " + superClassName
+ "\nImplements: " + impl);
String[] implNames = null;
if(impl.size() != 0)
implNames = impl.toArray(new String[impl.size()]);
cl.visit(classVersion, access, className, null, superClassName, implNames);
}
@SuppressWarnings("unused")
private static String getAccessModifiers(int access){
LinkedList<String> modifiers = new LinkedList<String>();
if((Opcodes.ACC_ABSTRACT & access) == Opcodes.ACC_ABSTRACT){
modifiers.add("abstract");
}
if((Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION){
modifiers.add("annotation");
}
if((Opcodes.ACC_BRIDGE & access) == Opcodes.ACC_BRIDGE){
modifiers.add("bridge");
}
if((Opcodes.ACC_DEPRECATED & access) == Opcodes.ACC_DEPRECATED){
modifiers.add("deprecated");
}
if((Opcodes.ACC_ENUM & access) == Opcodes.ACC_ENUM){
modifiers.add("enum");
}
if((Opcodes.ACC_FINAL & access) == Opcodes.ACC_FINAL){
modifiers.add("final");
}
if((Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE){
modifiers.add("interface");
}
if((Opcodes.ACC_MANDATED & access) == Opcodes.ACC_MANDATED){
modifiers.add("mandated");
}
if((Opcodes.ACC_NATIVE & access) == Opcodes.ACC_NATIVE){
modifiers.add("native");
}
if((Opcodes.ACC_PRIVATE & access) == Opcodes.ACC_PRIVATE){
modifiers.add("private");
}
if((Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED){
modifiers.add("protected");
}
if((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC){
modifiers.add("public");
}
if((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC){
modifiers.add("static");
}
if((Opcodes.ACC_STRICT & access) == Opcodes.ACC_STRICT){
modifiers.add("strict");
}
if((Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER){
modifiers.add("super");
}
if((Opcodes.ACC_SYNCHRONIZED & access) == Opcodes.ACC_SYNCHRONIZED){
modifiers.add("synchronized");
}
if((Opcodes.ACC_SYNTHETIC & access) == Opcodes.ACC_SYNTHETIC){
modifiers.add("synthetic");
}
if((Opcodes.ACC_TRANSIENT & access) == Opcodes.ACC_TRANSIENT){
modifiers.add("transient");
}
if((Opcodes.ACC_VARARGS & access) == Opcodes.ACC_VARARGS){
modifiers.add("varargs");
}
if((Opcodes.ACC_VOLATILE & access) == Opcodes.ACC_VOLATILE){
modifiers.add("volatile");
}
return modifiers.toString();
}
@SuppressWarnings("unused")
private static String getAccessModifiers(int access){
LinkedList<String> modifiers = new LinkedList<String>();
if((Opcodes.ACC_ABSTRACT & access) == Opcodes.ACC_ABSTRACT){
modifiers.add("abstract");
}
if((Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION){
modifiers.add("annotation");
}
if((Opcodes.ACC_BRIDGE & access) == Opcodes.ACC_BRIDGE){
modifiers.add("bridge");
}
if((Opcodes.ACC_DEPRECATED & access) == Opcodes.ACC_DEPRECATED){
modifiers.add("deprecated");
}
if((Opcodes.ACC_ENUM & access) == Opcodes.ACC_ENUM){
modifiers.add("enum");
}
if((Opcodes.ACC_FINAL & access) == Opcodes.ACC_FINAL){
modifiers.add("final");
}
if((Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE){
modifiers.add("interface");
}
if((Opcodes.ACC_MANDATED & access) == Opcodes.ACC_MANDATED){
modifiers.add("mandated");
}
if((Opcodes.ACC_NATIVE & access) == Opcodes.ACC_NATIVE){
modifiers.add("native");
}
if((Opcodes.ACC_PRIVATE & access) == Opcodes.ACC_PRIVATE){
modifiers.add("private");
}
if((Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED){
modifiers.add("protected");
}
if((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC){
modifiers.add("public");
}
if((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC){
modifiers.add("static");
}
if((Opcodes.ACC_STRICT & access) == Opcodes.ACC_STRICT){
modifiers.add("strict");
}
if((Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER){
modifiers.add("super");
}
if((Opcodes.ACC_SYNCHRONIZED & access) == Opcodes.ACC_SYNCHRONIZED){
modifiers.add("synchronized");
}
if((Opcodes.ACC_SYNTHETIC & access) == Opcodes.ACC_SYNTHETIC){
modifiers.add("synthetic");
}
if((Opcodes.ACC_TRANSIENT & access) == Opcodes.ACC_TRANSIENT){
modifiers.add("transient");
}
if((Opcodes.ACC_VARARGS & access) == Opcodes.ACC_VARARGS){
modifiers.add("varargs");
}
if((Opcodes.ACC_VOLATILE & access) == Opcodes.ACC_VOLATILE){
modifiers.add("volatile");
}
return modifiers.toString();
}
/**
* Gets the class access flags (see JVMS8 4.1) for the given type element, augmented by the
* special ASM pseudo-access flag for @Deprecated types.
*/
public int getAccessFlags(TypeElement typeElement) {
ElementKind kind;
try {
kind = typeElement.getKind();
} catch (CannotInferException e) {
Preconditions.checkState(typeElement.getNestingKind().isNested());
// We cannot know the access flags of an inferred type element. However, the only
// flag that matters in the InnerClasses table is ACC_STATIC. When reading the
// InnerClasses table, the compiler may create ClassSymbols for types it hasn't
// seen before, and the absence of ACC_STATIC will cause it to mark those
// ClassSymbols as inner classes, and it will not correct that when later loading
// the class from its definitive class file. However, it is safe to mark
// everything with ACC_STATIC, because the compiler *will* properly update
// non-static classes when loading their definitive class files.
// (http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/file/9986bf97a48d/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java#l2272)
return Opcodes.ACC_STATIC;
}
int result = getCommonAccessFlags(typeElement);
switch (kind) {
case ANNOTATION_TYPE:
// No ACC_SUPER here per JVMS 4.1
result = result | Opcodes.ACC_ANNOTATION;
result = result | Opcodes.ACC_INTERFACE;
result = result | Opcodes.ACC_ABSTRACT;
break;
case ENUM:
result = result | Opcodes.ACC_SUPER; // JVMS 4.1
result = result | Opcodes.ACC_ENUM;
if (isAbstractEnum(typeElement)) {
result = result & ~Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT;
}
break;
case INTERFACE:
// No ACC_SUPER here per JVMS 4.1
result = result | Opcodes.ACC_ABSTRACT;
result = result | Opcodes.ACC_INTERFACE;
break;
// $CASES-OMITTED$
default:
result = result | Opcodes.ACC_SUPER; // JVMS 4.1
break;
}
return result;
}