List of usage examples for org.objectweb.asm Opcodes ACC_STATIC
int ACC_STATIC
To view the source code for org.objectweb.asm Opcodes ACC_STATIC.
Click Source Link
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(); }