Example usage for org.objectweb.asm Opcodes ACC_STATIC

List of usage examples for org.objectweb.asm Opcodes ACC_STATIC

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes ACC_STATIC.

Prototype

int ACC_STATIC

To view the source code for org.objectweb.asm Opcodes ACC_STATIC.

Click Source Link

Usage

From source file:org.spongepowered.asm.mixin.transformer.MixinTransformer.java

License:MIT License

/**
 * Field sanity checks//from w  w  w .java  2 s. co  m
 * @param mixin
 * @param field
 * @param shadow
 */
private void validateField(MixinTargetContext mixin, FieldNode field, AnnotationNode shadow) {
    // Public static fields will fall foul of early static binding in java, including them in a mixin is an error condition
    if (MixinTransformer.hasFlag(field, Opcodes.ACC_STATIC)
            && !MixinTransformer.hasFlag(field, Opcodes.ACC_PRIVATE)) {
        throw new InvalidMixinException(mixin, String
                .format("Mixin classes cannot contain visible static methods or fields, found %s", field.name));
    }

    // Shadow fields can't have prefixes, it's meaningless for them anyway
    String prefix = ASMHelper.<String>getAnnotationValue(shadow, "prefix", Shadow.class);
    if (field.name.startsWith(prefix)) {
        throw new InvalidMixinException(mixin, String
                .format("Shadow field %s in %s has a shadow prefix. This is not allowed.", field.name, mixin));
    }
}

From source file:org.spongepowered.asm.mixin.transformer.MixinTransformer.java

License:MIT License

/**
 * Mixin methods from the mixin class into the target class
 * //from   w w w  .  ja v  a 2  s. co m
 * @param targetClass
 * @param mixin
 */
private void applyMixinMethods(ClassNode targetClass, MixinTargetContext mixin) {
    for (MethodNode mixinMethod : mixin.getClassNode().methods) {
        // Reparent all mixin methods into the target class
        mixin.transformMethod(mixinMethod);

        boolean isShadow = ASMHelper.getVisibleAnnotation(mixinMethod, Shadow.class) != null;
        boolean isOverwrite = ASMHelper.getVisibleAnnotation(mixinMethod, Overwrite.class) != null;
        boolean isAbstract = MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_ABSTRACT);

        if (isShadow || isAbstract) {
            // For shadow (and abstract, which can be used as a shorthand for Shadow) methods, we just check they're present
            MethodNode target = this.findTargetMethod(targetClass, mixinMethod);
            if (target == null) {
                throw new InvalidMixinException(mixin, String
                        .format("Shadow method %s was not located in the target class", mixinMethod.name));
            }
        } else if (!mixinMethod.name.startsWith("<")) {
            if (MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_STATIC)
                    && !MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_PRIVATE)
                    && !MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_SYNTHETIC) && !isOverwrite) {
                throw new InvalidMixinException(mixin,
                        String.format("Mixin classes cannot contain visible static methods or fields, found %s",
                                mixinMethod.name));
            }

            this.mergeMethod(targetClass, mixin, mixinMethod, isOverwrite);
        } else if (MixinTransformer.CLINIT.equals(mixinMethod.name)) {
            // Class initialiser insns get appended
            this.appendInsns(targetClass, mixinMethod.name, mixinMethod);
        }
    }
}

From source file:org.spongepowered.asm.mixin.transformer.MixinTransformer.java

License:MIT License

/**
 * Validates and prepares an intrinsic merge, returns true if the intrinsic
 * check results in a "skip" action, indicating that no further merge action
 * should be undertaken/* ww w .  j a  v  a  2s.co m*/
 * 
 * @param targetClass Target classnode
 * @param mixin Mixin context
 * @param method Method being merged
 * @param isOverwrite True if the incoming method is tagged with Override
 * @param target target method being checked
 * @param intrinsic {@link Intrinsic} annotation
 * @return true if the intrinsic method was skipped (short-circuit further
 *      merge operations)
 */
private boolean mergeIntrinsic(ClassNode targetClass, MixinTargetContext mixin, MethodNode method,
        boolean isOverwrite, MethodNode target, AnnotationNode intrinsic) {

    if (isOverwrite) {
        throw new InvalidMixinException(mixin,
                "@Intrinsic is not compatible with @Overwrite, remove one of these annotations on "
                        + method.name);
    }

    if (MixinTransformer.hasFlag(method, Opcodes.ACC_STATIC)) {
        throw new InvalidMixinException(mixin, "@Intrinsic method cannot be static, found " + method.name);
    }

    AnnotationNode renamed = ASMHelper.getVisibleAnnotation(method, MixinRenamed.class);
    if (renamed == null || !ASMHelper.getAnnotationValue(renamed, "isInterfaceMember", false)) {
        throw new InvalidMixinException(mixin,
                "@Intrinsic method must be prefixed interface method, no rename encountered on " + method.name);
    }

    if (!ASMHelper.getAnnotationValue(intrinsic, "displace", false)) {
        this.logger.log(mixin.getLoggingLevel(), "Skipping Intrinsic mixin method {}", method.name);
        return true;
    }

    this.displaceIntrinsic(targetClass, mixin, method, target);
    return false;
}

From source file:org.spongepowered.asm.util.Locals.java

License:MIT License

/**
 * <p>Attempts to identify available locals at an arbitrary point in the
 * bytecode specified by node.</p>
 * //from  w ww  .  ja  v a  2s .  c  o  m
 * <p>This method builds an approximate view of the locals available at an
 * arbitrary point in the bytecode by examining the following features in
 * the bytecode:</p> 
 * <ul>
 *   <li>Any available stack map frames</li>
 *   <li>STORE opcodes</li>
 *   <li>The local variable table</li>
 * </ul>
 * 
 * <p>Inference proceeds by walking the bytecode from the start of the
 * method looking for stack frames and STORE opcodes. When either of these
 * is encountered, an attempt is made to cross-reference the values in the
 * stack map or STORE opcode with the value in the local variable table
 * which covers the code range. Stack map frames overwrite the entire
 * simulated local variable table with their own value types, STORE opcodes
 * overwrite only the local slot to which they pertain. Values in the
 * simulated locals array are spaced according to their size (unlike the
 * representation in FrameNode) and this TOP, NULL and UNINTITIALIZED_THIS
 * opcodes will be represented as null values in the simulated frame.</p>
 * 
 * <p>This code does not currently simulate the prescribed JVM behaviour
 * where overwriting the second slot of a DOUBLE or LONG actually
 * invalidates the DOUBLE or LONG stored in the previous location, so we
 * have to hope (for now) that this behaviour isn't emitted by the compiler
 * or any upstream transformers. I may have to re-think this strategy if
 * this situation is encountered in the wild.</p>
 * 
 * @param classNode ClassNode containing the method, used to initialise the
 *      implicit "this" reference in simple methods with no stack frames
 * @param method MethodNode to explore
 * @param node Node indicating the position at which to determine the locals
 *      state. The locals will be enumerated UP TO the specified node, so
 *      bear in mind that if the specified node is itself a STORE opcode,
 *      then we will be looking at the state of the locals PRIOR to its
 *      invocation
 * @return A sparse array containing a view (hopefully) of the locals at the
 *      specified location
 */
public static LocalVariableNode[] getLocalsAt(ClassNode classNode, MethodNode method, AbstractInsnNode node) {
    LocalVariableNode[] frame = new LocalVariableNode[method.maxLocals];
    int local = 0, index = 0;

    // Initialise implicit "this" reference in non-static methods
    if ((method.access & Opcodes.ACC_STATIC) == 0) {
        frame[local++] = new LocalVariableNode("this", classNode.name, null, null, null, 0);
    }

    // Initialise method arguments
    for (Type argType : Type.getArgumentTypes(method.desc)) {
        frame[local] = new LocalVariableNode("arg" + index++, argType.toString(), null, null, null, local);
        local += argType.getSize();
    }

    for (Iterator<AbstractInsnNode> iter = method.instructions.iterator(); iter.hasNext();) {
        AbstractInsnNode insn = iter.next();
        if (insn instanceof FrameNode) {
            FrameNode frameNode = (FrameNode) insn;

            // localPos tracks the location in the frame node's locals list, which doesn't leave space for TOP entries
            for (int localPos = 0, framePos = 0; framePos < frame.length; framePos++, localPos++) {
                // Get the local at the current position in the FrameNode's locals list
                final Object localType = (localPos < frameNode.local.size()) ? frameNode.local.get(localPos)
                        : null;

                if (localType instanceof String) { // String refers to a reference type
                    frame[framePos] = Locals.getLocalVariableAt(classNode, method, node, framePos);
                } else if (localType instanceof Integer) { // Integer refers to a primitive type or other marker
                    boolean isMarkerType = localType == Opcodes.UNINITIALIZED_THIS || localType == Opcodes.TOP
                            || localType == Opcodes.NULL;
                    boolean is32bitValue = localType == Opcodes.INTEGER || localType == Opcodes.FLOAT;
                    boolean is64bitValue = localType == Opcodes.DOUBLE || localType == Opcodes.LONG;
                    if (isMarkerType) {
                        frame[framePos] = null;
                    } else if (is32bitValue || is64bitValue) {
                        frame[framePos] = Locals.getLocalVariableAt(classNode, method, node, framePos);

                        if (is64bitValue) {
                            framePos++;
                            frame[framePos] = null; // TOP
                        }
                    } else {
                        throw new RuntimeException(
                                "Unrecognised locals opcode " + localType + " in locals array at position "
                                        + localPos + " in " + classNode.name + "." + method.name + method.desc);
                    }
                } else if (localType == null) {
                    frame[framePos] = null;
                } else {
                    throw new RuntimeException("Invalid value " + localType + " in locals array at position "
                            + localPos + " in " + classNode.name + "." + method.name + method.desc);
                }
            }
        } else if (insn instanceof VarInsnNode) {
            VarInsnNode varNode = (VarInsnNode) insn;
            frame[varNode.var] = Locals.getLocalVariableAt(classNode, method, node, varNode.var);
        } else if (insn == node) {
            break;
        }
    }

    return frame;
}

From source file:org.spongepowered.despector.ast.io.insn.InstructionTreeBuilder.java

License:Open Source License

@SuppressWarnings("unchecked")
public static StatementBlock build(MethodNode asm) {
    if (asm.instructions.size() == 0) {
        return null;
    }//w w w.  j  av a 2 s .c om
    Locals locals = new Locals();
    Set<String> names = Sets.newHashSet();
    for (LocalVariableNode node : (List<LocalVariableNode>) asm.localVariables) {
        Local local = locals.getLocal(node.index);
        String name = node.name;
        if ("".equals(name)) {
            name = "local";
        }
        if (names.contains(name)) {
            String possible_name = name + "1";
            int i = 1;
            while (names.contains(possible_name)) {
                possible_name = name + (++i);
            }
            name = possible_name;
        }
        local.setName(name);
        names.add(name);
        local.setType(node.desc);
        if (node.signature != null) {
            String[] generics = TypeHelper.getGenericContents(node.signature);
            local.setGenericTypes(generics);
        }
    }
    int offs = ((asm.access & Opcodes.ACC_STATIC) != 0) ? 1 : 0;
    for (int i = 0; i <= TypeHelper.paramCount(asm.desc) - offs; i++) {
        locals.getLocal(i).setAsParameter();
    }
    return new OpcodeDecompiler().decompile(asm.instructions, locals);
}

From source file:org.spongepowered.mod.asm.transformers.MixinTransformer.java

License:MIT License

/**
 * Mixin fields from mixin class into the target class. It is vital that this is done before mixinMethods because we need to compute renamed
 * fields so that transformMethod can rename field references in the method body
 * //from   w  w w  .j  a  va 2 s.  com
 * @param targetClass
 * @param mixin
 */
private void applyMixinFields(ClassNode targetClass, MixinData mixin) {
    for (FieldNode field : mixin.getClassNode().fields) {
        // Public static fields will fall foul of early static binding in java, including them in a mixin is an error condition
        if (MixinTransformer.hasFlag(field, Opcodes.ACC_STATIC)
                && !MixinTransformer.hasFlag(field, Opcodes.ACC_PRIVATE)) {
            throw new InvalidMixinException(String.format(
                    "Mixin classes cannot contain visible static methods or fields, found %s", field.name));
        }

        FieldNode target = this.findTargetField(targetClass, field);
        if (target == null) {
            // If this field is a shadow field but is NOT found in the target class, that's bad, mmkay
            boolean isShadow = ASMHelper.getVisibleAnnotation(field, Shadow.class) != null;
            if (isShadow) {
                throw new InvalidMixinException(
                        String.format("Shadow field %s was not located in the target class", field.name));
            }

            // This is just a local field, so add it
            targetClass.fields.add(field);
        } else {
            // Check that the shadow field has a matching descriptor
            if (!target.desc.equals(field.desc)) {
                throw new InvalidMixinException(String
                        .format("The field %s in the target class has a conflicting signature", field.name));
            }
        }
    }
}

From source file:org.spongepowered.mod.asm.transformers.MixinTransformer.java

License:MIT License

/**
 * Mixin methods from the mixin class into the target class
 * //from w w w . ja v  a 2  s.  c  o m
 * @param targetClass
 * @param mixin
 */
private void applyMixinMethods(ClassNode targetClass, MixinData mixin) {
    for (MethodNode mixinMethod : mixin.getClassNode().methods) {
        // Reparent all mixin methods into the target class
        this.transformMethod(mixinMethod, mixin.getClassNode().name, targetClass.name);

        boolean isShadow = ASMHelper.getVisibleAnnotation(mixinMethod, Shadow.class) != null;
        boolean isOverwrite = ASMHelper.getVisibleAnnotation(mixinMethod, Overwrite.class) != null;
        boolean isAbstract = MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_ABSTRACT);

        if (isShadow || isAbstract) {
            // For shadow (and abstract, which can be used as a shorthand for Shadow) methods, we just check they're present
            MethodNode target = this.findTargetMethod(targetClass, mixinMethod);
            if (target == null) {
                throw new InvalidMixinException(String
                        .format("Shadow method %s was not located in the target class", mixinMethod.name));
            }
        } else if (!mixinMethod.name.startsWith("<")) {
            if (MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_STATIC)
                    && !MixinTransformer.hasFlag(mixinMethod, Opcodes.ACC_PRIVATE) && !isOverwrite) {
                throw new InvalidMixinException(
                        String.format("Mixin classes cannot contain visible static methods or fields, found %s",
                                mixinMethod.name));
            }

            MethodNode target = this.findTargetMethod(targetClass, mixinMethod);
            if (target != null) {
                targetClass.methods.remove(target);
            } else if (isOverwrite) {
                throw new InvalidMixinException(String
                        .format("Overwrite target %s was not located in the target class", mixinMethod.name));
            }
            targetClass.methods.add(mixinMethod);
        } else if ("<clinit>".equals(mixinMethod.name)) {
            // Class initialiser insns get appended
            this.appendInsns(targetClass, mixinMethod.name, mixinMethod);
        }
    }
}

From source file:org.spongepowered.mod.asm.util.ASMHelper.java

License:MIT License

/**
 * Generate a forwarding method of the form
 * "static T name(S object) { return object.forward(); }".
 *
 * @param clazz Class to generate new method on
 * @param name Name of method to generate
 * @param forwardname Name of method to call
 * @param rettype Return type of method//from www  . j av a2s.c om
 */
public static void generateStaticForwardingMethod(ClassNode clazz, String name, String forwardname,
        Type rettype, Type argtype) {
    MethodNode method = new MethodNode(Opcodes.ASM5,
            Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, name,
            "()" + rettype.getDescriptor(), null, null);

    populateSelfForwardingMethod(method, forwardname, rettype, argtype);

    clazz.methods.add(method);
}

From source file:org.springframework.core.type.classreading.ClassMetadataReadingVisitor.java

License:Apache License

public void visitInnerClass(String name, String outerName, String innerName, int access) {
    if (outerName != null) {
        String fqName = ClassUtils.convertResourcePathToClassName(name);
        String fqOuterName = ClassUtils.convertResourcePathToClassName(outerName);
        if (this.className.equals(fqName)) {
            this.enclosingClassName = fqOuterName;
            this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0);
        } else if (this.className.equals(fqOuterName)) {
            this.memberClassNames.add(fqName);
        }/*from  www  .  j av a  2 s .  c o m*/
    }
}

From source file:org.springframework.migrationanalyzer.contributions.bytecode.AsmUtils.java

License:Apache License

/**
 * Converts the given bitwise ORed <code>modifiers</code> into a {@link String}.
 * // www  . j a  va2s  . c  o m
 * <p/>
 * 
 * The returned String should reflect the ordering recommended in the JLS:
 * 
 * <ul>
 * <li>Classes: <code>public protected private abstract static final strictfp</code></li>
 * <li>Fields: <code>public protected private static final transient volatile</code></li>
 * <li>Constructors: <code>public protected private</code></li>
 * <li>Methods: <code>public protected private abstract static final synchronized native strictfp</code></li>
 * </ul>
 * 
 * @param modifiers the modifiers
 * 
 * @return The String representation of the modifiers
 * 
 * @see Opcodes
 */
// CHECKSTYLE:OFF
static final String modifiersToString(int modifiers) {
    StringBuilder accessBuilder = new StringBuilder();

    if ((modifiers & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC) {
        accessBuilder.append("public ");
    }
    if ((modifiers & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED) {
        accessBuilder.append("protected ");
    }
    if ((modifiers & Opcodes.ACC_PRIVATE) == Opcodes.ACC_PRIVATE) {
        accessBuilder.append("private ");
    }
    if ((modifiers & Opcodes.ACC_ABSTRACT) == Opcodes.ACC_ABSTRACT) {
        accessBuilder.append("abstract ");
    }
    if ((modifiers & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC) {
        accessBuilder.append("static ");
    }
    if ((modifiers & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL) {
        accessBuilder.append("final ");
    }
    if ((modifiers & Opcodes.ACC_SYNCHRONIZED) == Opcodes.ACC_SYNCHRONIZED) {
        accessBuilder.append("synchronized ");
    }
    if ((modifiers & Opcodes.ACC_NATIVE) == Opcodes.ACC_NATIVE) {
        accessBuilder.append("native ");
    }
    if ((modifiers & Opcodes.ACC_TRANSIENT) == Opcodes.ACC_TRANSIENT) {
        accessBuilder.append("transient ");
    }
    if ((modifiers & Opcodes.ACC_VOLATILE) == Opcodes.ACC_VOLATILE) {
        accessBuilder.append("volatile ");
    }
    if ((modifiers & Opcodes.ACC_STRICT) == Opcodes.ACC_STRICT) {
        accessBuilder.append("strictfp ");
    }

    return accessBuilder.toString().trim();
}