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:com.google.devtools.build.android.desugar.CoreLibrarySupport.java

License:Open Source License

/** Includes the given method definition in any applicable core interface emulation logic. */
public void registerIfEmulatedCoreInterface(int access, String owner, String name, String desc,
        String[] exceptions) {//w  ww  . ja v a 2  s .c  o  m
    Class<?> emulated = getEmulatedCoreClassOrInterface(owner);
    if (emulated == null) {
        return;
    }
    checkArgument(emulated.isInterface(), "Shouldn't be called for a class: %s.%s", owner, name);
    checkArgument(
            BitFlags.noneSet(access,
                    Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE | Opcodes.ACC_STATIC | Opcodes.ACC_BRIDGE),
            "Should only be called for default methods: %s.%s", owner, name);
    emulatedDefaultMethods.put(name + ":" + desc,
            EmulatedMethod.create(access, emulated, name, desc, exceptions));
}

From source file:com.google.devtools.build.android.desugar.CoreLibrarySupport.java

License:Open Source License

private void makeDispatchHelperMethod(ClassVisitor helper, EmulatedMethod method,
        ImmutableList<Class<?>> typechecks) {
    checkArgument(method.owner().isInterface());
    String owner = method.owner().getName().replace('.', '/');
    Type methodType = Type.getMethodType(method.descriptor());
    String companionDesc = InterfaceDesugaring.companionDefaultMethodDescriptor(owner, method.descriptor());
    MethodVisitor dispatchMethod = helper.visitMethod(method.access() | Opcodes.ACC_STATIC, method.name(),
            companionDesc, /*signature=*/ null, // signature is invalid due to extra "receiver" argument
            method.exceptions().toArray(EMPTY_LIST));

    dispatchMethod.visitCode();/*from   ww  w.ja v  a2 s. c  o  m*/
    {
        // See if the receiver might come with its own implementation of the method, and call it.
        // We do this by testing for the interface type created by EmulatedInterfaceRewriter
        Label fallthrough = new Label();
        String emulationInterface = renameCoreLibrary(owner);
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.INSTANCEOF, emulationInterface);
        dispatchMethod.visitJumpInsn(Opcodes.IFEQ, fallthrough);
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.CHECKCAST, emulationInterface);

        visitLoadArgs(dispatchMethod, methodType, 1 /* receiver already loaded above */);
        dispatchMethod.visitMethodInsn(Opcodes.INVOKEINTERFACE, emulationInterface, method.name(),
                method.descriptor(), /*itf=*/ true);
        dispatchMethod.visitInsn(methodType.getReturnType().getOpcode(Opcodes.IRETURN));

        dispatchMethod.visitLabel(fallthrough);
        // Trivial frame for the branch target: same empty stack as before
        dispatchMethod.visitFrame(Opcodes.F_SAME, 0, EMPTY_FRAME, 0, EMPTY_FRAME);
    }

    // Next, check for subtypes with specialized implementations and call them
    for (Class<?> tested : typechecks) {
        Label fallthrough = new Label();
        String testedName = tested.getName().replace('.', '/');
        // In case of a class this must be a member move; for interfaces use the companion.
        String target = tested.isInterface() ? InterfaceDesugaring.getCompanionClassName(testedName)
                : checkNotNull(memberMoves.get(rewriter.unprefix(testedName) + '#' + method.name()));
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.INSTANCEOF, testedName);
        dispatchMethod.visitJumpInsn(Opcodes.IFEQ, fallthrough);
        dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
        dispatchMethod.visitTypeInsn(Opcodes.CHECKCAST, testedName); // make verifier happy

        visitLoadArgs(dispatchMethod, methodType, 1 /* receiver already loaded above */);
        dispatchMethod.visitMethodInsn(Opcodes.INVOKESTATIC, target, method.name(),
                InterfaceDesugaring.companionDefaultMethodDescriptor(testedName, method.descriptor()),
                /*itf=*/ false);
        dispatchMethod.visitInsn(methodType.getReturnType().getOpcode(Opcodes.IRETURN));

        dispatchMethod.visitLabel(fallthrough);
        // Trivial frame for the branch target: same empty stack as before
        dispatchMethod.visitFrame(Opcodes.F_SAME, 0, EMPTY_FRAME, 0, EMPTY_FRAME);
    }

    // Call static type's default implementation in companion class
    dispatchMethod.visitVarInsn(Opcodes.ALOAD, 0); // load "receiver"
    visitLoadArgs(dispatchMethod, methodType, 1 /* receiver already loaded above */);
    dispatchMethod.visitMethodInsn(Opcodes.INVOKESTATIC, InterfaceDesugaring.getCompanionClassName(owner),
            method.name(), companionDesc, /*itf=*/ false);
    dispatchMethod.visitInsn(methodType.getReturnType().getOpcode(Opcodes.IRETURN));

    dispatchMethod.visitMaxs(0, 0);
    dispatchMethod.visitEnd();
}

From source file:com.google.devtools.build.android.desugar.DefaultMethodClassFixer.java

License:Open Source License

private void recordIfInstanceMethod(int access, String name, String desc) {
    if (BitFlags.noneSet(access, Opcodes.ACC_STATIC)) {
        // Record all declared instance methods, including abstract, bridge, and native methods, as
        // they all take precedence over default methods.
        instanceMethods.add(name + ":" + desc);
    }//from w w  w .j  a  v a2 s .  c o m
}

From source file:com.google.devtools.build.android.desugar.DefaultMethodClassFixer.java

License:Open Source License

/**
 * Returns {@code true} for non-bridge default methods not in {@link #instanceMethods}.
 *//* w w  w  . j  a  v  a 2s  .  c  o  m*/
private boolean shouldStub(int access, String name, String desc) {
    // Ignore private methods, which technically aren't default methods and can only be called from
    // other methods defined in the interface.  This also ignores lambda body methods, which is fine
    // as we don't want or need to stub those.  Also ignore bridge methods as javac adds them to
    // concrete classes as needed anyway and we handle them separately for generated lambda classes.
    return BitFlags.noneSet(access,
            Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_PRIVATE)
            && !instanceMethods.contains(name + ":" + desc);
}

From source file:com.google.devtools.build.android.desugar.InterfaceDesugaring.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    MethodVisitor result;/*from w  w w.  j  av  a 2s. c  o m*/
    if (BitFlags.isSet(accessFlags, Opcodes.ACC_INTERFACE)
            && BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_BRIDGE)
            && !"<clinit>".equals(name)) {
        checkArgument(BitFlags.noneSet(access, Opcodes.ACC_NATIVE), "Forbidden per JLS ch 9.4");

        boolean isLambdaBody = name.startsWith("lambda$") && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC);
        if (isLambdaBody) {
            access &= ~Opcodes.ACC_PUBLIC; // undo visibility change from LambdaDesugaring
            // Rename lambda method to reflect the new owner.  Not doing so confuses LambdaDesugaring
            // if it's run over this class again.
            name += COMPANION_SUFFIX;
        }
        if (BitFlags.isSet(access, Opcodes.ACC_STATIC)) {
            // Completely move static interface methods, which requires rewriting call sites
            result = companion().visitMethod(access & ~Opcodes.ACC_PRIVATE, name, desc, signature, exceptions);
        } else {
            MethodVisitor abstractDest;
            if (isLambdaBody) {
                // Completely move lambda bodies, which requires rewriting call sites
                access &= ~Opcodes.ACC_PRIVATE;
                abstractDest = null;
            } else {
                // Make default methods abstract but move their implementation into a static method with
                // corresponding signature.  Doesn't require callsite rewriting but implementing classes
                // may need to implement default methods explicitly.
                checkArgument(BitFlags.noneSet(access, Opcodes.ACC_PRIVATE),
                        "Unexpected private interface method %s.%s : %s", name, internalName, desc);
                abstractDest = super.visitMethod(access | Opcodes.ACC_ABSTRACT, name, desc, signature,
                        exceptions);
            }

            // TODO(b/37110951): adjust signature with explicit receiver type, which may be generic
            MethodVisitor codeDest = companion().visitMethod(access | Opcodes.ACC_STATIC, name,
                    companionDefaultMethodDescriptor(internalName, desc), (String) null, // drop signature, since given one doesn't include the new param
                    exceptions);

            result = abstractDest != null ? new MultiplexAnnotations(codeDest, abstractDest) : codeDest;
        }
    } else {
        result = super.visitMethod(access, name, desc, signature, exceptions);
    }
    return result != null ? new InterfaceInvocationRewriter(result) : null;
}

From source file:com.google.devtools.build.android.desugar.Java7Compatibility.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    // Remove bridge default methods in interfaces; javac generates them again for implementing
    // classes anyways.
    if (isInterface && (access
            & (Opcodes.ACC_BRIDGE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC)) == Opcodes.ACC_BRIDGE) {
        return null;
    }//w  w w  .j  a  v a  2 s .c  o  m
    if (isInterface && "$jacocoInit".equals(name)
            && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC)) {
        // Drop static interface method that Jacoco generates--we'll inline it into the static
        // initializer instead
        return null;
    }
    // TODO(b/31547323): Avoid stack trace and report errors more user-friendly
    checkArgument(!isInterface || BitFlags.isSet(access, Opcodes.ACC_ABSTRACT) || "<clinit>".equals(name),
            "Interface %s defines non-abstract method %s%s, which is not supported", internalName, name, desc);
    MethodVisitor result = super.visitMethod(access, name, desc, signature, exceptions);
    return (isInterface && "<clinit>".equals(name)) ? new InlineJacocoInit(result) : result;
}

From source file:com.google.devtools.build.android.desugar.LambdaClassFixer.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    if (name.equals("writeReplace") && BitFlags.noneSet(access, Opcodes.ACC_STATIC)
            && desc.equals("()Ljava/lang/Object;")) {
        // Lambda serialization hooks use java/lang/invoke/SerializedLambda, which isn't available on
        // Android. Since Jack doesn't do anything special for serializable lambdas we just drop these
        // serialization hooks.
        // https://docs.oracle.com/javase/8/docs/platform/serialization/spec/output.html#a5324 gives
        // details on the role and signature of this method.
        return null;
    }//  ww w . ja v a2  s  .c  om
    if (BitFlags.noneSet(access, Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC)) {
        // Keep track of instance methods implemented in this class for later.  Since this visitor
        // is intended for lambda classes, no need to look at the superclass.
        implementedMethods.add(name + ":" + desc);
    }
    if (FACTORY_METHOD_NAME.equals(name)) {
        hasFactory = true;
        if (!lambdaInfo.needFactory()) {
            return null; // drop generated factory method if we won't call it
        }
        access &= ~Opcodes.ACC_PRIVATE; // make factory method accessible
    } else if ("<init>".equals(name)) {
        this.desc = desc;
        this.signature = signature;
        if (!lambdaInfo.needFactory() && !desc.startsWith("()")) {
            access &= ~Opcodes.ACC_PRIVATE; // make constructor accessible if we'll call it directly
        }
    }
    MethodVisitor methodVisitor = new LambdaClassMethodRewriter(
            super.visitMethod(access, name, desc, signature, exceptions));
    if (!lambdaInfo.bridgeMethod().equals(lambdaInfo.methodReference())) {
        // Skip UseBridgeMethod unless we actually need it
        methodVisitor = new UseBridgeMethod(methodVisitor, lambdaInfo, access, name, desc, signature,
                exceptions);
    }
    if (!FACTORY_METHOD_NAME.equals(name) && !"<init>".equals(name)) {
        methodVisitor = new LambdaClassInvokeSpecialRewriter(methodVisitor);
    }
    return methodVisitor;
}

From source file:com.google.devtools.build.android.desugar.LambdaClassFixer.java

License:Open Source License

@Override
public void visitEnd() {
    checkState(!hasState || hasFactory, "Expected factory method for capturing lambda %s", getInternalName());
    if (!hasState) {
        checkState(signature == null, "Didn't expect generic constructor signature %s %s", getInternalName(),
                signature);/*from  w  w w  .ja  va  2s .  c o  m*/
        checkState(lambdaInfo.factoryMethodDesc().startsWith("()"),
                "Expected 0-arg factory method for %s but found %s", getInternalName(),
                lambdaInfo.factoryMethodDesc());
        // Since this is a stateless class we populate and use a static singleton field "$instance".
        // Field is package-private so we can read it from the class that had the invokedynamic.
        String singletonFieldDesc = lambdaInfo.factoryMethodDesc().substring("()".length());
        super.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, SINGLETON_FIELD_NAME, singletonFieldDesc,
                (String) null, (Object) null).visitEnd();

        MethodVisitor codeBuilder = super.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", (String) null,
                new String[0]);
        codeBuilder.visitTypeInsn(Opcodes.NEW, getInternalName());
        codeBuilder.visitInsn(Opcodes.DUP);
        codeBuilder.visitMethodInsn(Opcodes.INVOKESPECIAL, getInternalName(), "<init>",
                checkNotNull(desc, "didn't see a constructor for %s", getInternalName()), /*itf*/ false);
        codeBuilder.visitFieldInsn(Opcodes.PUTSTATIC, getInternalName(), SINGLETON_FIELD_NAME,
                singletonFieldDesc);
        codeBuilder.visitInsn(Opcodes.RETURN);
        codeBuilder.visitMaxs(2, 0); // two values are pushed onto the stack
        codeBuilder.visitEnd();
    }

    copyRewrittenLambdaMethods();
    if (!allowDefaultMethods) {
        copyBridgeMethods(interfaces);
    }
    super.visitEnd();
}

From source file:com.google.devtools.build.android.desugar.LambdaDesugaring.java

License:Open Source License

@Override
public void visitEnd() {
    for (Map.Entry<Handle, MethodReferenceBridgeInfo> bridge : bridgeMethods.entrySet()) {
        Handle original = bridge.getKey();
        Handle neededMethod = bridge.getValue().bridgeMethod();
        checkState(// w  w w.  ja  v a2  s . c o  m
                neededMethod.getTag() == Opcodes.H_INVOKESTATIC
                        || neededMethod.getTag() == Opcodes.H_INVOKEVIRTUAL,
                "Cannot generate bridge method %s to reach %s", neededMethod, original);
        checkState(bridge.getValue().referenced() != null, "Need referenced method %s to generate bridge %s",
                original, neededMethod);

        int access = Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_FINAL;
        if (neededMethod.getTag() == Opcodes.H_INVOKESTATIC) {
            access |= Opcodes.ACC_STATIC;
        }
        MethodVisitor bridgeMethod = super.visitMethod(access, neededMethod.getName(), neededMethod.getDesc(),
                (String) null, toInternalNames(bridge.getValue().referenced().getExceptionTypes()));

        // Bridge is a factory method calling a constructor
        if (original.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
            bridgeMethod.visitTypeInsn(Opcodes.NEW, original.getOwner());
            bridgeMethod.visitInsn(Opcodes.DUP);
        }

        int slot = 0;
        if (neededMethod.getTag() != Opcodes.H_INVOKESTATIC) {
            bridgeMethod.visitVarInsn(Opcodes.ALOAD, slot++);
        }
        Type neededType = Type.getMethodType(neededMethod.getDesc());
        for (Type arg : neededType.getArgumentTypes()) {
            bridgeMethod.visitVarInsn(arg.getOpcode(Opcodes.ILOAD), slot);
            slot += arg.getSize();
        }
        bridgeMethod.visitMethodInsn(invokeOpcode(original), original.getOwner(), original.getName(),
                original.getDesc(), original.isInterface());
        bridgeMethod.visitInsn(neededType.getReturnType().getOpcode(Opcodes.IRETURN));

        bridgeMethod.visitMaxs(0, 0); // rely on class writer to compute these
        bridgeMethod.visitEnd();
    }
    super.visitEnd();
}

From source file:com.google.devtools.build.android.desugar.LambdaDesugaring.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    if (name.equals("$deserializeLambda$") && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC)) {
        // Android doesn't do anything special for lambda serialization so drop the special
        // deserialization hook that javac generates.  This also makes sure we don't reference
        // java/lang/invoke/SerializedLambda, which doesn't exist on Android.
        return null;
    }//from  w  ww .  ja v a  2s.c o  m
    if (name.startsWith("lambda$") && BitFlags.isSet(access, Opcodes.ACC_SYNTHETIC)) {
        if (!allowDefaultMethods && isInterface && BitFlags.isSet(access, Opcodes.ACC_STATIC)) {
            // There must be a lambda in the interface (which in the absence of hand-written default or
            // static interface methods must mean it's in the <clinit> method or inside another lambda).
            // We'll move this method out of this class, so just record and drop it here.
            // (Note lambda body methods have unique names, so we don't need to remember desc here.)
            aggregateInterfaceLambdaMethods.add(internalName + '#' + name);
            return null;
        }
        if (BitFlags.isSet(access, Opcodes.ACC_PRIVATE)) {
            // Make lambda body method accessible from lambda class
            access &= ~Opcodes.ACC_PRIVATE;
            if (allowDefaultMethods && isInterface) {
                // java 8 requires interface methods to have exactly one of ACC_PUBLIC and ACC_PRIVATE
                access |= Opcodes.ACC_PUBLIC;
            } else {
                // Method was private so it can be final, which should help VMs perform dispatch.
                access |= Opcodes.ACC_FINAL;
            }
        }
        // Guarantee unique lambda body method name to avoid accidental overriding. This wouldn't be
        // be necessary for static methods but in visitOuterClass we don't know whether a potential
        // outer lambda$ method is static or not, so we just always do it.
        name = uniqueInPackage(internalName, name);
    }
    MethodVisitor dest = super.visitMethod(access, name, desc, signature, exceptions);
    return dest != null ? new InvokedynamicRewriter(dest, access, name, desc, signature, exceptions) : null;
}