下面列出了org.objectweb.asm.Opcodes# ACC_INTERFACE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* {@inheritDoc}
*/
public TypeManifestation getTypeManifestation() {
int modifiers = getModifiers();
switch (modifiers & (Opcodes.ACC_ANNOTATION | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_FINAL)) {
case Opcodes.ACC_FINAL:
return TypeManifestation.FINAL;
case Opcodes.ACC_ABSTRACT:
return TypeManifestation.ABSTRACT;
case Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE:
return TypeManifestation.INTERFACE;
case Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION:
return TypeManifestation.ANNOTATION;
case EMPTY_MASK:
return TypeManifestation.PLAIN;
default:
throw new IllegalStateException("Unexpected modifiers: " + modifiers);
}
}
static ClassInformation getClassInformation(final InputStream is) throws IOException {
ClassReader classReader = new ClassReader(is);
String name = classReader.getClassName();
String superName = classReader.getSuperName();
String[] interfaces = classReader.getInterfaces();
boolean interfaceMarker = (classReader.getAccess() & Opcodes.ACC_INTERFACE) != 0;
return new ClassInformation(name, superName, Arrays.asList(interfaces), interfaceMarker);
}
/**
* Returns a ClassReader corresponding to the given class or interface.
*
* @param type
* the internal name of a class or interface.
* @return the ClassReader corresponding to 'type'.
* @throws IOException
* if the bytecode of 'type' cannot be loaded.
*/
private TypeInfo loadTypeInfo(String type) throws IOException {
InputStream is = loader.getResourceAsStream(type + ".class");
try {
ClassReader info = new ClassReader(is);
return new TypeInfo(info.getClassName(),
info.getSuperName(),
info.getInterfaces(),
(info.getAccess() & Opcodes.ACC_INTERFACE) != 0);
} finally {
is.close();
}
}
private boolean instrument() {
if ((access & Opcodes.ACC_INTERFACE) != 0) return false;
for(String p: excludePackages) {
if (className.startsWith(p)) return false;
}
return true;
}
@Override
public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
if ((classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0) {
// does not apply on interfaces
return;
}
if (!(classNode instanceof InnerClassNode)) {
addTimeStamp(classNode);
}
}
/**
* Returns a ClassReader corresponding to the given class or interface.
*
* @param type
* the internal name of a class or interface.
* @return the ClassReader corresponding to 'type'.
* @throws IOException
* if the bytecode of 'type' cannot be loaded.
*/
private TypeInfo loadTypeInfo(String type) throws IOException {
InputStream is = loader.getResourceAsStream(type + ".class");
try {
ClassReader info = new ClassReader(is);
return new TypeInfo(info.getClassName(),
info.getSuperName(),
info.getInterfaces(),
(info.getAccess() & Opcodes.ACC_INTERFACE) != 0);
} finally {
is.close();
}
}
/**
* Ensures that the class contains a $starkChange field used for referencing the IncrementalChange
* dispatcher.
* <p>
* <p>Also updates package_private visibility to public so we can call into this class from
* outside the package.
*/
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
visitedClassName = name;
visitedSuperName = superName;
isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
int fieldAccess =
isInterface
? Opcodes.ACC_PUBLIC
| Opcodes.ACC_STATIC
| Opcodes.ACC_SYNTHETIC
| Opcodes.ACC_FINAL
: Opcodes.ACC_PUBLIC
| Opcodes.ACC_STATIC
| Opcodes.ACC_VOLATILE
| Opcodes.ACC_SYNTHETIC
| Opcodes.ACC_TRANSIENT;
// when dealing with interfaces, the $starkChange field is an AtomicReference to the CHANGE_TYPE
// since fields in interface must be final. For classes, it's the CHANGE_TYPE directly.
if (isInterface) {
super.visitField(
fieldAccess,
"$starkChange",
getRuntimeTypeName(Type.getType(AtomicReference.class)),
null,
null);
} else {
super.visitField(fieldAccess, "$starkChange", getRuntimeTypeName(CHANGE_TYPE), null, null);
}
access = transformClassAccessForStark(access);
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visit(
int version,
int access,
String name,
String signature,
String superName,
String[] interfaces) {
this.className = name;
if ((access & (Opcodes.ACC_INTERFACE)) != 0) {
// Interfaces don't have vtables.
// This might undercount annotations, but they are mostly small.
isInterface = true;
} else {
// Some parent classes have big vtable footprints. We try to estimate the parent vtable
// size based on the name of the class and parent class. This seems to work reasonably
// well in practice because the heaviest vtables are View and Activity, and many of those
// classes have clear names and cannot be obfuscated.
// Non-interfaces inherit the java.lang.Object vtable, which is 48 bytes.
int vtablePenalty = 48;
String[] names = new String[] {name, superName};
for (Map.Entry<Pattern, Integer> entry : penalties.entrySet()) {
for (String cls : names) {
if (entry.getKey().matcher(cls).find()) {
vtablePenalty = Math.max(vtablePenalty, entry.getValue());
}
}
}
footprint += vtablePenalty;
}
}
@Override
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
ClassInfo superClass = null;
superClass = superName == null ? null : repository.getClass(namer.nameClass(superName));
List<ClassInfo> interfaceList = new ArrayList<ClassInfo>();
for (String interfaze : interfaces) {
interfaceList.add(repository.getClass(namer.nameClass(interfaze)));
}
boolean isInterface = (access & Opcodes.ACC_INTERFACE) == Opcodes.ACC_INTERFACE;
classInfo = new ClassInfo(namer.nameClass(name), isInterface, superClass,
interfaceList, guessSourceFileName(name));
repository.addClass(classInfo);
}
@Override
public void visit(
int api, int access, String name, String sig, String superClass, String[] exceptions) {
System.out.println("NAME:" + name);
System.out.println("SUPER:" + superClass);
System.out.println("sig:" + sig);
if (sig != null) {
boolean isInterface = (Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE;
SignatureReader signatureReader = new SignatureReader(sig);
this.visitor = new ClassSignatureVisitor(this.name, isInterface);
signatureReader.accept(this.visitor);
}
}
/**
* Checks the given class.
*
* @param classReader the class to be checked.
* @param loader a <code>ClassLoader</code> which will be used to load referenced classes. May be
* {@literal null}.
* @param printResults whether to print the results of the bytecode verification.
* @param printWriter where the results (or the stack trace in case of error) must be printed.
*/
public static void verify(
final ClassReader classReader,
final ClassLoader loader,
final boolean printResults,
final PrintWriter printWriter) {
ClassNode classNode = new ClassNode();
classReader.accept(
new CheckClassAdapter(Opcodes.ASM7, classNode, false) {}, ClassReader.SKIP_DEBUG);
Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName);
List<MethodNode> methods = classNode.methods;
List<Type> interfaces = new ArrayList<Type>();
for (String interfaceName : classNode.interfaces) {
interfaces.add(Type.getObjectType(interfaceName));
}
for (MethodNode method : methods) {
SimpleVerifier verifier =
new SimpleVerifier(
Type.getObjectType(classNode.name),
syperType,
interfaces,
(classNode.access & Opcodes.ACC_INTERFACE) != 0);
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(verifier);
if (loader != null) {
verifier.setClassLoader(loader);
}
try {
analyzer.analyze(classNode.name, method);
} catch (AnalyzerException e) {
e.printStackTrace(printWriter);
}
if (printResults) {
printAnalyzerResult(method, analyzer, printWriter);
}
}
printWriter.flush();
}
private boolean instrument() {
return (access & Opcodes.ACC_INTERFACE) == 0;
}
final boolean hasInterfaceDeclReason() {
return hasDeclReason() && (ownerAccess() & Opcodes.ACC_INTERFACE) != 0;
}
/**
* Computes and returns the value of SVUID.
*
* @return the serial version UID.
* @throws IOException if an I/O error occurs.
*/
// DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
protected long computeSVUID() throws IOException {
long svuid = 0;
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream)) {
// 1. The class name written using UTF encoding.
dataOutputStream.writeUTF(name.replace('/', '.'));
// 2. The class modifiers written as a 32-bit integer.
int mods = access;
if ((mods & Opcodes.ACC_INTERFACE) != 0) {
mods =
svuidMethods.isEmpty() ? (mods & ~Opcodes.ACC_ABSTRACT) : (mods | Opcodes.ACC_ABSTRACT);
}
dataOutputStream.writeInt(
mods
& (Opcodes.ACC_PUBLIC
| Opcodes.ACC_FINAL
| Opcodes.ACC_INTERFACE
| Opcodes.ACC_ABSTRACT));
// 3. The name of each interface sorted by name written using UTF encoding.
Arrays.sort(interfaces);
for (String interfaceName : interfaces) {
dataOutputStream.writeUTF(interfaceName.replace('/', '.'));
}
// 4. For each field of the class sorted by field name (except private static and private
// transient fields):
// 1. The name of the field in UTF encoding.
// 2. The modifiers of the field written as a 32-bit integer.
// 3. The descriptor of the field in UTF encoding.
// Note that field signatures are not dot separated. Method and constructor signatures are dot
// separated. Go figure...
writeItems(svuidFields, dataOutputStream, false);
// 5. If a class initializer exists, write out the following:
// 1. The name of the method, <clinit>, in UTF encoding.
// 2. The modifier of the method, ACC_STATIC, written as a 32-bit integer.
// 3. The descriptor of the method, ()V, in UTF encoding.
if (hasStaticInitializer) {
dataOutputStream.writeUTF(CLINIT);
dataOutputStream.writeInt(Opcodes.ACC_STATIC);
dataOutputStream.writeUTF("()V");
}
// 6. For each non-private constructor sorted by method name and signature:
// 1. The name of the method, <init>, in UTF encoding.
// 2. The modifiers of the method written as a 32-bit integer.
// 3. The descriptor of the method in UTF encoding.
writeItems(svuidConstructors, dataOutputStream, true);
// 7. For each non-private method sorted by method name and signature:
// 1. The name of the method in UTF encoding.
// 2. The modifiers of the method written as a 32-bit integer.
// 3. The descriptor of the method in UTF encoding.
writeItems(svuidMethods, dataOutputStream, true);
dataOutputStream.flush();
// 8. The SHA-1 algorithm is executed on the stream of bytes produced by DataOutputStream and
// produces five 32-bit values sha[0..4].
byte[] hashBytes = computeSHAdigest(byteArrayOutputStream.toByteArray());
// 9. The hash value is assembled from the first and second 32-bit values of the SHA-1 message
// digest. If the result of the message digest, the five 32-bit words H0 H1 H2 H3 H4, is in an
// array of five int values named sha, the hash value would be computed as follows:
for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
}
}
return svuid;
}
@Override
public void visit(
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
if ((access & Opcodes.ACC_MODULE) != 0) {
// Modules are printed in visitModule.
return;
}
this.access = access;
int majorVersion = version & 0xFFFF;
int minorVersion = version >>> 16;
stringBuilder.setLength(0);
stringBuilder
.append("// class version ")
.append(majorVersion)
.append('.')
.append(minorVersion)
.append(" (")
.append(version)
.append(")\n");
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
stringBuilder.append(DEPRECATED);
}
appendRawAccess(access);
appendDescriptor(CLASS_SIGNATURE, signature);
if (signature != null) {
appendJavaDeclaration(name, signature);
}
appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE));
if ((access & Opcodes.ACC_ANNOTATION) != 0) {
stringBuilder.append("@interface ");
} else if ((access & Opcodes.ACC_INTERFACE) != 0) {
stringBuilder.append("interface ");
} else if ((access & Opcodes.ACC_ENUM) == 0) {
stringBuilder.append("class ");
}
appendDescriptor(INTERNAL_NAME, name);
if (superName != null && !"java/lang/Object".equals(superName)) {
stringBuilder.append(" extends ");
appendDescriptor(INTERNAL_NAME, superName);
}
if (interfaces != null && interfaces.length > 0) {
stringBuilder.append(" implements ");
for (int i = 0; i < interfaces.length; ++i) {
appendDescriptor(INTERNAL_NAME, interfaces[i]);
if (i != interfaces.length - 1) {
stringBuilder.append(' ');
}
}
}
stringBuilder.append(" {\n\n");
text.add(stringBuilder.toString());
}
/**
* Convert an ASM access mask to a reflection Modifier mask.
*
* @param asmAccessMask the ASM access mask
*
* @return the Modifier mask
*/
private int convertAccessMaskToModifierMask(int asmAccessMask)
{
int modifier = 0;
// Convert the ASM access info into Reflection API modifiers.
if ((asmAccessMask & Opcodes.ACC_FINAL) != 0)
modifier |= Modifier.FINAL;
if ((asmAccessMask & Opcodes.ACC_NATIVE) != 0)
modifier |= Modifier.NATIVE;
if ((asmAccessMask & Opcodes.ACC_INTERFACE) != 0)
modifier |= Modifier.INTERFACE;
if ((asmAccessMask & Opcodes.ACC_ABSTRACT) != 0)
modifier |= Modifier.ABSTRACT;
if ((asmAccessMask & Opcodes.ACC_PRIVATE) != 0)
modifier |= Modifier.PRIVATE;
if ((asmAccessMask & Opcodes.ACC_PROTECTED) != 0)
modifier |= Modifier.PROTECTED;
if ((asmAccessMask & Opcodes.ACC_PUBLIC) != 0)
modifier |= Modifier.PUBLIC;
if ((asmAccessMask & Opcodes.ACC_STATIC) != 0)
modifier |= Modifier.STATIC;
if ((asmAccessMask & Opcodes.ACC_STRICT) != 0)
modifier |= Modifier.STRICT;
if ((asmAccessMask & Opcodes.ACC_SYNCHRONIZED) != 0)
modifier |= Modifier.SYNCHRONIZED;
if ((asmAccessMask & Opcodes.ACC_TRANSIENT) != 0)
modifier |= Modifier.TRANSIENT;
if ((asmAccessMask & Opcodes.ACC_VOLATILE) != 0)
modifier |= Modifier.VOLATILE;
return modifier;
}
@Override
public void visit(
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
if ((access & Opcodes.ACC_MODULE) != 0) {
// Modules are printed in visitModule.
return;
}
this.access = access;
int majorVersion = version & 0xFFFF;
int minorVersion = version >>> 16;
stringBuilder.setLength(0);
stringBuilder
.append("// class version ")
.append(majorVersion)
.append('.')
.append(minorVersion)
.append(" (")
.append(version)
.append(")\n");
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
stringBuilder.append(DEPRECATED);
}
appendRawAccess(access);
appendDescriptor(CLASS_SIGNATURE, signature);
if (signature != null) {
appendJavaDeclaration(name, signature);
}
appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE));
if ((access & Opcodes.ACC_ANNOTATION) != 0) {
stringBuilder.append("@interface ");
} else if ((access & Opcodes.ACC_INTERFACE) != 0) {
stringBuilder.append("interface ");
} else if ((access & Opcodes.ACC_ENUM) == 0) {
stringBuilder.append("class ");
}
appendDescriptor(INTERNAL_NAME, name);
if (superName != null && !"java/lang/Object".equals(superName)) {
stringBuilder.append(" extends ");
appendDescriptor(INTERNAL_NAME, superName);
}
if (interfaces != null && interfaces.length > 0) {
stringBuilder.append(" implements ");
for (int i = 0; i < interfaces.length; ++i) {
appendDescriptor(INTERNAL_NAME, interfaces[i]);
if (i != interfaces.length - 1) {
stringBuilder.append(' ');
}
}
}
stringBuilder.append(" {\n\n");
text.add(stringBuilder.toString());
}
@Override
public final void visitCode() {
if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
sa.addStart("code", new AttributesImpl());
}
}
public boolean isInterface() {
return (this.access & Opcodes.ACC_INTERFACE) != 0;
}
private boolean isInterface(final ClassReader classReader) {
return (classReader.getAccess() & Opcodes.ACC_INTERFACE) != 0;
}