GithubHelp home page GithubHelp logo

Comments (3)

raphw avatar raphw commented on July 19, 2024

This is absolutely possible. In general, you are able to create any possible Java class by using the exposed ASM-API. However, for your example, you can even use the ASM wrapper classes that already ship with Byte Buddy to implement this.

Please see my answer on StackOverflow (http://stackoverflow.com/questions/24711172/how-in-java-to-assign-to-fields-with-byte-buddy/24735122#24735122) for how to implement this with Byte Buddy.

from byte-buddy.

binkley avatar binkley commented on July 19, 2024

Thanks!

That I can tell I am unable to create new methods, only to
override/implement existing methods. For example I tried making an "a()"
method to access the "a" field on a class extending Object, and discovered
the "a()" method is always not found.

package lab.bytegen;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.instrumentation.Instrumentation;
import net.bytebuddy.instrumentation.Instrumentation.Context;
import net.bytebuddy.instrumentation.Instrumentation.Target;
import net.bytebuddy.instrumentation.method.MethodDescription;
import net.bytebuddy.instrumentation.method.bytecode.ByteCodeAppender;
import net.bytebuddy.instrumentation.method.bytecode.stack.StackManipulation;
import net.bytebuddy.instrumentation.method.bytecode.stack.member.FieldAccess;
import net.bytebuddy.instrumentation.method.bytecode.stack.member.MethodInvocation;
import net.bytebuddy.instrumentation.method.bytecode.stack.member.MethodReturn;
import net.bytebuddy.instrumentation.type.InstrumentedType;
import net.bytebuddy.instrumentation.type.TypeDescription;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.modifier.FieldManifestation;
import net.bytebuddy.modifier.TypeManifestation;

import java.lang.reflect.Field;
import java.util.Arrays;

import static java.lang.System.out;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static net.bytebuddy.ClassFileVersion.JAVA_V8;
import static net.bytebuddy.dynamic.ClassLoadingStrategy.Default.INJECTION;
import static net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy.Default.NO_CONSTRUCTORS;
import static net.bytebuddy.instrumentation.method.bytecode.stack.member.MethodVariableAccess

    .INTEGER;

import static net.bytebuddy.instrumentation.method.bytecode.stack.member.MethodVariableAccess
.REFERENCE;
import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.isConstructor;
import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.isMethod;
import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.named;
import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.returns;
import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.takesArguments;
import static net.bytebuddy.modifier.Visibility.PRIVATE;
import static net.bytebuddy.modifier.Visibility.PUBLIC;

/**

  • {@code WriteAClassMain} needs documentation.
    *

  • @author B. K. Oxley (binkley)

  • @see <a href="http://stackoverflow.com/questions/24711172/how-in-java-to-assign-to-fields-with

  • -byte-buddy">How in Java to assign to fields with Byte Buddy?
    */
    public final class WriteAClassMain {

    public static void main(final String... args)
    throws Exception {

    final Class<?> aClass = new ByteBuddy().
            subclass(Object.class, NO_CONSTRUCTORS).
    
            classFileVersion(JAVA_V8).
            modifiers(PUBLIC, TypeManifestation.FINAL).
    
            name("foo.AClass").
            defineField("a", int.class, PRIVATE, FieldManifestation.FINAL).
    
            defineConstructor(singletonList(int.class), PUBLIC).
    
            intercept(new IntFieldInterceptor("a", IntFieldPutter::new)).
    
            defineMethod("a", int.class, emptyList(), PUBLIC).
    
            intercept(new IntFieldInterceptor("a", IntFieldGetter::new)).
    
            make().
            // saveIn(File file).
            load(WriteAClassMain.class.getClassLoader(), INJECTION).
    
            getLoaded();
    final Object o = aClass.
            getConstructor(int.class).
    
            newInstance(3);
    out.println(Arrays.toString(aClass.getDeclaredFields()));
    out.println(Arrays.toString(aClass.getDeclaredConstructors()));
    out.println(Arrays.toString(aClass.getDeclaredMethods()));
    final Field a = aClass.getDeclaredField("a");
    a.setAccessible(true);
    out.println(a.get(o));
    

    }

    private interface I {
    ByteCodeAppender i(final Target instrumentationTarget, final
    String name);
    }

    private static final class IntFieldInterceptor
    implements Instrumentation {

    private final String name;
    private final I i;
    
    IntFieldInterceptor(final String name, I i) {
    
        this.name = name;
        this.i = i;
    }
    
    @Override
    public InstrumentedType prepare(final InstrumentedType
    

    instrumentedType) {

        return instrumentedType;
    }
    
    @Override
    public ByteCodeAppender appender(final Target instrumentationTarget) {
    
        return i.i(instrumentationTarget, name);
    }
    

    }

    private static final class IntFieldPutter
    implements ByteCodeAppender {

    private final Target instrumentationTarget;
    private final String name;
    
    IntFieldPutter(final Target instrumentationTarget, final String name) {
    
        this.instrumentationTarget = instrumentationTarget;
        this.name = name;
    }
    
    @Override
    public boolean appendsCode() {
    
        return true;
    }
    
    @Override
    public Size apply(final MethodVisitor methodVisitor, final
    

    Context instrumentationContext,
    final MethodDescription instrumentedMethod) {
    final StackManipulation arg0 = REFERENCE.loadFromIndex(0);
    final StackManipulation iArg1 = INTEGER.loadFromIndex(1);
    final StackManipulation.Size size = new
    StackManipulation.Compound(arg0,
    MethodInvocation.invoke(new
    TypeDescription.ForLoadedType(Object.class).

                        getDeclaredMethods().
                        filter(isConstructor().
                                and(takesArguments(0))).
    
                        getOnly()), arg0, iArg1,
    

    FieldAccess.forField(instrumentationTarget.

                getTypeDescription().
                getDeclaredFields().
                named(name)).
                putter(), MethodReturn.VOID).
    
                apply(methodVisitor, instrumentationContext);
        return new Size(size.getMaximalSize(),
    

    instrumentedMethod.getStackSize());
    }
    }

    private static final class IntFieldGetter
    implements ByteCodeAppender {

    private final Target instrumentationTarget;
    private final String name;
    
    IntFieldGetter(final Target instrumentationTarget, final String name) {
    
        this.instrumentationTarget = instrumentationTarget;
        this.name = name;
    }
    
    @Override
    public boolean appendsCode() {
    
        return true;
    }
    
    @Override
    public Size apply(final MethodVisitor methodVisitor, final
    

    Context instrumentationContext,
    final MethodDescription instrumentedMethod) {
    final StackManipulation arg0 = REFERENCE.loadFromIndex(0);
    final StackManipulation.Size size = new
    StackManipulation.Compound(arg0,
    MethodInvocation.invoke(new
    TypeDescription.ForLoadedType(Object.class).

                        getDeclaredMethods().
                        // TODO: No such method in Object
                                filter(isMethod().
    
                                and(named(name)).
                                and(takesArguments(0)).
    
                                and(returns(int.class))).
                        getOnly()), arg0,
    

    FieldAccess.forField(instrumentationTarget.

                getTypeDescription().
                getDeclaredFields().
                named(name)).
                getter(), MethodReturn.INTEGER).
    
                apply(methodVisitor, instrumentationContext);
        return new Size(size.getMaximalSize(),
    

    instrumentedMethod.getStackSize());
    }
    }
    }

Cheers,
--binkley

On Fri, Jul 18, 2014 at 6:03 PM, Rafael Winterhalter <
[email protected]> wrote:

This is absolutely possible. In general, you are able to create any
possible Java class by using the exposed ASM-API. However, for your
example, you can even use the ASM wrapper classes that already ship with
Byte Buddy to implement this.

Please see my answer on StackOverflow (
http://stackoverflow.com/questions/24711172/how-in-java-to-assign-to-fields-with-byte-buddy/24735122#24735122)
for how to implement this with Byte Buddy.


Reply to this email directly or view it on GitHub
#3 (comment).

from byte-buddy.

raphw avatar raphw commented on July 19, 2024

It looks like you are trying to find a method named a in the Object class:

TypeDescription.ForLoadedType(Object.class)
  .getDeclaredMethods()
  .filter(isMethod(). and(named(name)). and(takesArguments(0)). and(returns(int.class)))
  .getOnly();

The Object class does however not define any method named a. Rather check instrumentationTarget.getTypeDescription() for the method which you defined for your newly defined type (the instrumentation target's type).

from byte-buddy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.