下面列出了org.objectweb.asm.Opcodes# ACC_PROTECTED 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void visit(final int version, final int access, final String name,
final String signature, final String superName, final String[] interfaces) {
/*
* Record the original access bits so we can restore them before the next
* link in the visitor chain.
*/
originalClassAccess = access;
accessCaptured = true;
// If we're checking an inner class, suppress access bits that ASM chokes on.
int checkClassAccess = access;
if (name.indexOf('$') >= 0) {
checkClassAccess &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
}
super.visit(version, checkClassAccess, name, signature, superName, interfaces);
}
private String renameMethod(MethodNode methodToRename) {
// first remove any annotations from renamed base methods
AnnotationUtils.clearMethodAnnotations(methodToRename);
// rename the method
String originalMethodName = methodToRename.name;
String renamedMethodName = mergeRenamePrefix + methodToRename.name;
methodToRename.name = renamedMethodName;
// make the method private to hide it from the end user
methodToRename.access = methodToRename.access & (~Opcodes.ACC_PUBLIC & ~Opcodes.ACC_PROTECTED & ~Opcodes.ACC_PRIVATE);
methodToRename.access = methodToRename.access | Opcodes.ACC_PRIVATE;
Log.info("Renamed " + originalMethodName + " to " + renamedMethodName);
return originalMethodName; // return the original name
}
/**
* Checks that the given access flags do not contain invalid flags. This
* method also checks that mutually incompatible flags are not set
* simultaneously.
*
* @param access
* the access flags to be checked
* @param possibleAccess
* the valid access flags.
*/
static void checkAccess(final int access, final int possibleAccess) {
if ((access & ~possibleAccess) != 0) {
throw new IllegalArgumentException("Invalid access flags: " + access);
}
int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
if (pub + pri + pro > 1) {
throw new IllegalArgumentException("public private and protected are mutually exclusive: " + access);
}
int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
if (fin + abs > 1) {
throw new IllegalArgumentException("final and abstract are mutually exclusive: " + access);
}
}
@Test
public void parseRegularModel() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(Crud.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visit("value", "entity");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("model");
assertThat(element.getAttribute("filter")).contains("=entity)");
}
@Test
public void parseModelOnNotCrudField() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(String.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visit("value", "entity");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("model");
assertThat(element.getAttribute("filter")).contains("=entity)");
}
/**
* Gets the class access flags (see JVMS8 4.1) for the given type element as they should appear in
* the ClassNode of a class file. Inner-class specific flags are not allowed in that node,
* presumably for compatibility reasons.
*/
public int getAccessFlagsForClassNode(TypeElement e) {
// Static never makes it into the file for classes
int accessFlags = getAccessFlags(e) & ~Opcodes.ACC_STATIC;
if (e.getNestingKind() != NestingKind.TOP_LEVEL) {
if (e.getModifiers().contains(Modifier.PROTECTED)) {
// It looks like inner classes with protected visibility get marked as public, and then
// their InnerClasses attributes override that more specifically
accessFlags = (accessFlags & ~Opcodes.ACC_PROTECTED) | Opcodes.ACC_PUBLIC;
} else if (e.getModifiers().contains(Modifier.PRIVATE)) {
// It looks like inner classes with private visibility get marked as package, and then
// their InnerClasses attributes override that more specifically
accessFlags = (accessFlags & ~Opcodes.ACC_PRIVATE);
}
}
return accessFlags;
}
@Test
public void parseViewOnNotTemplateField() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "template", Type.getDescriptor(String.class), null, null);
WisdomViewVisitor visitor = new WisdomViewVisitor(workbench, reporter, node);
visitor.visit("value", "index");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("template");
assertThat(element.getAttribute("filter")).contains("=index)");
}
/**
* Checks that the given access flags do not contain invalid flags. This method also checks that
* mutually incompatible flags are not set simultaneously.
*
* @param access the access flags to be checked.
* @param possibleAccess the valid access flags.
*/
static void checkAccess(final int access, final int possibleAccess) {
if ((access & ~possibleAccess) != 0) {
throw new IllegalArgumentException("Invalid access flags: " + access);
}
int publicProtectedPrivate = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE;
if (Integer.bitCount(access & publicProtectedPrivate) > 1) {
throw new IllegalArgumentException(
"public, protected and private are mutually exclusive: " + access);
}
if (Integer.bitCount(access & (Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT)) > 1) {
throw new IllegalArgumentException("final and abstract are mutually exclusive: " + access);
}
}
@Override
public FieldVisitor visitField(
final int access,
final String name,
final String desc,
final String signature,
final Object value) {
// Get the class field information for step 4 of the algorithm. Also determine if the class
// already has a SVUID.
if (computeSvuid) {
if ("serialVersionUID".equals(name)) {
// Since the class already has SVUID, we won't be computing it.
computeSvuid = false;
hasSvuid = true;
}
// Collect the non private fields. Only the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED,
// ACC_STATIC, ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when computing
// serialVersionUID values.
if ((access & Opcodes.ACC_PRIVATE) == 0
|| (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
int mods =
access
& (Opcodes.ACC_PUBLIC
| Opcodes.ACC_PRIVATE
| Opcodes.ACC_PROTECTED
| Opcodes.ACC_STATIC
| Opcodes.ACC_FINAL
| Opcodes.ACC_VOLATILE
| Opcodes.ACC_TRANSIENT);
svuidFields.add(new Item(name, mods, desc));
}
}
return super.visitField(access, name, desc, signature, value);
}
@Override
public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
String s = remapper.mapMethodName(className, name, desc);
if ("-".equals(s)) {
return null;
}
if (name.equals("<clinit>") && !isInterface) {
hasClinitMethod = true;
MethodVisitor mv =
super.visitMethod(access, name, desc, null, exceptions);
return new MethodVisitor(Opcodes.ASM5, mv) {
@Override
public void visitCode() {
super.visitCode();
mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName, "_clinit_", "()V", false);
}
};
}
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
return super.visitMethod(access, name, desc, null, exceptions);
} else {
if (!s.equals(name)) {
throw new RuntimeException("The public or protected method " + className + '.' + name + desc + " must not be renamed.");
}
return super.visitMethod(access, name, desc, null, exceptions);
}
}
@Test
public void parseEmptyAnnotation() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(Crud.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visitEnd();
assertThat(elements).hasSize(0);
}
public static String getAccessString(int access) {
List<String> tokens = new ArrayList<>();
if ((access & Opcodes.ACC_PUBLIC) != 0)
tokens.add("public");
if ((access & Opcodes.ACC_PRIVATE) != 0)
tokens.add("private");
if ((access & Opcodes.ACC_PROTECTED) != 0)
tokens.add("protected");
if ((access & Opcodes.ACC_FINAL) != 0)
tokens.add("final");
if ((access & Opcodes.ACC_SYNTHETIC) != 0)
tokens.add("synthetic");
// if ((access & Opcodes.ACC_SUPER) != 0)
// tokens.add("super"); implied by invokespecial insn
if ((access & Opcodes.ACC_ABSTRACT) != 0)
tokens.add("abstract");
if ((access & Opcodes.ACC_INTERFACE) != 0)
tokens.add("interface");
if ((access & Opcodes.ACC_ENUM) != 0)
tokens.add("enum");
if ((access & Opcodes.ACC_ANNOTATION) != 0)
tokens.add("annotation");
if (!tokens.contains("interface") && !tokens.contains("enum") && !tokens.contains("annotation"))
tokens.add("class");
if (tokens.size() == 0)
return "[Error parsing]";
// hackery delimeters
StringBuilder sb = new StringBuilder(tokens.get(0));
for (int i = 1; i < tokens.size(); i++) {
sb.append(" ");
sb.append(tokens.get(i));
}
return sb.toString();
}
/** Gets the access flag (see JVMS8 4.1, 4.5, 4.6) corresponding to the given modifier. */
private static int modifierToAccessFlag(Modifier modifier) {
switch (modifier) {
case PUBLIC:
return Opcodes.ACC_PUBLIC;
case PROTECTED:
return Opcodes.ACC_PROTECTED;
case PRIVATE:
return Opcodes.ACC_PRIVATE;
case ABSTRACT:
return Opcodes.ACC_ABSTRACT;
case DEFAULT:
return 0;
case STATIC:
return Opcodes.ACC_STATIC;
case FINAL:
return Opcodes.ACC_FINAL;
case TRANSIENT:
return Opcodes.ACC_TRANSIENT;
case VOLATILE:
return Opcodes.ACC_VOLATILE;
case SYNCHRONIZED:
return Opcodes.ACC_SYNCHRONIZED;
case NATIVE:
return Opcodes.ACC_NATIVE;
case STRICTFP:
return Opcodes.ACC_STRICT;
default:
throw new IllegalArgumentException(String.format("Unexpected modifier: %s", modifier));
}
}
@SuppressWarnings("SimplifiableIfStatement")
private static boolean isCallableFromSubclass(
@NonNull MethodNode method,
@NonNull ClassNode superClass,
@NonNull ClassNode subclass) {
if ((method.access & Opcodes.ACC_PRIVATE) != 0) {
return false;
} else if ((method.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) {
return true;
} else {
// "package private" access modifier.
return ByteCodeUtils.getPackageName(superClass.name).equals(ByteCodeUtils.getPackageName(subclass.name));
}
}
protected static String getAccessString(int access) {
// public, protected, private, abstract, static,
// final, synchronized, native & strictfp are permitted
List<String> tokens = new ArrayList<>();
if ((access & Opcodes.ACC_PUBLIC) != 0)
tokens.add("public");
if ((access & Opcodes.ACC_PRIVATE) != 0)
tokens.add("private");
if ((access & Opcodes.ACC_PROTECTED) != 0)
tokens.add("protected");
if ((access & Opcodes.ACC_STATIC) != 0)
tokens.add("static");
if ((access & Opcodes.ACC_ABSTRACT) != 0)
tokens.add("abstract");
if ((access & Opcodes.ACC_FINAL) != 0)
tokens.add("final");
if ((access & Opcodes.ACC_SYNCHRONIZED) != 0)
tokens.add("synchronized");
if ((access & Opcodes.ACC_NATIVE) != 0)
tokens.add("native");
if ((access & Opcodes.ACC_STRICT) != 0)
tokens.add("strictfp");
if ((access & Opcodes.ACC_BRIDGE) != 0)
tokens.add("bridge");
if ((access & Opcodes.ACC_VARARGS) != 0)
tokens.add("varargs");
if (tokens.size() == 0)
return "";
// hackery delimeters
StringBuilder sb = new StringBuilder(tokens.get(0));
for (int i = 1; i < tokens.size(); i++) {
sb.append(" ");
sb.append(tokens.get(i));
}
return sb.toString();
}
private int getBridgeAccessFlags(ExecutableElement method) {
return accessFlagsUtils.getAccessFlags(method)
& (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE)
| Opcodes.ACC_SYNTHETIC
| Opcodes.ACC_BRIDGE;
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (Modifier.isStatic(access) && !Modifier.isPublic(access)) {
if (Modifier.isPrivate(access)) {
access &= ~Opcodes.ACC_PRIVATE;
} else if (Modifier.isProtected(access)) {
access &= ~Opcodes.ACC_PROTECTED;
}
access += Opcodes.ACC_PUBLIC;
}
if (preserveInit) {
if (name.equals("<init>")) {// only inits ignore others
return super.visitMethod(access, name, desc, signature, exceptions);// dont touch
}
return null;
} else {
if (name.equals("<init>")) {
if (!addedEmptyInit) {
{// default...
MethodVisitor mv = super.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "<init>", "(Lcom/concurnas/bootstrap/runtime/InitUncreatable;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
if (superName.equals("java/lang/Object") || superName.equals("com/concurnas/bootstrap/runtime/cps/CObject")) {
mv.visitMethodInsn(INVOKESPECIAL, superName, "<init>", "()V", false);
} else {
mv.visitInsn(ACONST_NULL);
mv.visitMethodInsn(INVOKESPECIAL, superName, "<init>", "(Lcom/concurnas/bootstrap/runtime/InitUncreatable;)V", false);
}
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
addedEmptyInit = true;
}
// 1. if first for class, create standard init with call to superclass init
name = "init";
return new MethodAdjustor(super.visitMethod(ACC_PUBLIC, name, addInitU(desc), signature, exceptions), initInstanceToIsSuperConstru.get(new NameAndDesc("<init>", desc)), BcUtils.incArgPointsFromDesc(desc, access), true);
}
}
if (name.startsWith("lambda$") && Modifier.isPrivate(access)) {
access &= ~Opcodes.ACC_PRIVATE;// make lambdas public for purposes of access from 'global' instance
access += Opcodes.ACC_PUBLIC;
}
return new MethodAdjustor(super.visitMethod(access, name, desc, signature, exceptions), initInstanceToIsSuperConstru.get(new NameAndDesc(name, desc)), BcUtils.incArgPointsFromDesc(desc, access), false);
}
private static int makePublic(int i) {
return (i & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) | Opcodes.ACC_PUBLIC;
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
int newAccess =
access & (~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) | Opcodes.ACC_PUBLIC;
super.visitInnerClass(name, outerName, innerName, newAccess);
}
private boolean isProtect(int access) {
return (access & Opcodes.ACC_PROTECTED) != 0;
}