1

I have an strange behavior. Consider this code:

Every object that is returned from the database is created by this proxy:

public static <T> T bbcreate(Class<T> c, OElement ov, Transaction transaction ) {
        LOGGER.log(Level.FINEST, "create proxy for class: "+c+(c!=null?c.getName().toString():"NULL CLASS!!!!"));
        T po = null;
        try {
            Class<?> type = cache.findOrInsert(c.getClassLoader(), c, () -> {
                                return
                                    new ByteBuddy(ClassFileVersion.ofThisVm())
                                        .subclass(c)
                                        .defineField("___ogm___interceptor", ObjectProxy.class, Visibility.PUBLIC)
                                        .implement(IObjectProxy.class)
                                        .defineConstructor(Visibility.PUBLIC)
                                            .withParameter(ObjectProxy.class)
                                            .intercept(FieldAccessor.ofField("___ogm___interceptor").setsArgumentAt(0)
                                                        .andThen(MethodCall.invoke(c.getDeclaredConstructor()))
                                            )
                                        .method(ElementMatchers.any()) // isDeclaredBy(ITest.class)
                                            .intercept(MethodDelegation   // This.class,Origin.class,AllArguments.class,SuperMethod.class)
                                                        .withDefaultConfiguration() //.withBinders(TargetMethodAnnotationDrivenBinder.ParameterBinder.DEFAULTS)
                                                        .filter(ElementMatchers.named("intercept"))
                                                        .toField("___ogm___interceptor"))   // MethodDelegation.to(bbi)
                                        .make()
                                        .load(c.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                                        .getLoaded();
            });
            
            
            // crear el proxy al que delegar las llamadas
            ObjectProxy bbi = new ObjectProxy(c,ov,transaction);
            
            // crear una instancia
            po = (T)type.getConstructor(ObjectProxy.class).newInstance(bbi);
            
            bbi.___setProxiedObject(po);
            
            // clean possible dirtiness (because of actions in default constructor)
            bbi.___removeDirtyMark();
            
        } catch (InstantiationException | IllegalAccessException | SecurityException | NoSuchMethodException | IllegalArgumentException | InvocationTargetException ex) {
            Logger.getLogger(ObjectProxyFactory.class.getName()).log(Level.SEVERE, null, ex);
        }
        return po;
    }

The ObjectProxy's intercept method that is called is this:

// ByteBuddy interceptor 
    @RuntimeType
    public Object intercept(@This Object self, 
                            @Origin Method method, 
                            @AllArguments Object[] args, 
                            @SuperMethod(nullIfImpossible = true) Method superMethod,
                            @Empty Object defaultValue
                            ) throws Throwable {
        
//         
        
        // response object
        Object res = null;
        //this.___proxiedObject = self;
        // el estado del objeto se debe poder consultar siempre
        //=====================================================
        LOGGER.log(Level.FINEST, "=====================================================");
        LOGGER.log(Level.FINEST, self.getClass().getName() + " : "+ this.___baseElement.getRecord().getIdentity()+ " > method: "+method.getName()+"  superMethod: "+(superMethod!=null?superMethod.getName():"NULL"));
        LOGGER.log(Level.FINEST, "=====================================================");
        
        String debugLabel = this.___baseElement.getRecord().getIdentity()+ " > method: "+method.getName();
        
        if (method.getName().equals("___isValid")) {
            return this.___isValid();
        }
        
        if (method.getName().equals("___isDeleted")) {
            return this.___isDeleted();
        }

        if (method.getName().equals("___getVertex")) {
            return this.___getVertex();
        }
        if (method.getName().equals("___getEdge")) {
            return this.___getEdge();
        }
        if (method.getName().equals("___getElement")) {
            return this.___getElement();
        }

        if (method.getName().equals("___getRid")) {
            return this.___getRid();
        }
        
        if (method.getName().equals("___getBaseClass")) {
            return this.___getBaseClass();
        }

        if (!this.___isValidObject) {
            LOGGER.log(Level.FINER, "El objeto está marcado como inválido!!!");
            throw new InvalidObjectReference(this.___transaction);
        }

        if (method.getName().equals("___rollback")) {
            if (this.___objectReady) {
                this.___rollback();
                return true;
            }
        }

        if (this.___baseElement.getIdentity().isNew()) {
            LOGGER.log(Level.FINER, "RID nuevo. No procesar porque el store preparó todo y no hay nada que recuperar de la base.");
            this.___loadLazyLinks = false;
        }
        
        //if object was deleted:
        if (this.___deletedMark) {
            switch (method.getName()) {
                case "equals":
                case "hashCode":
                    if (!this.___transaction.getSessionManager().getConfig().
                            isEqualsAndHashCodeOnDeletedThrowsException()) {
                        return superMethod.invoke(self, args);
                    }
                default:
                    throw new ObjectMarkedAsDeleted("The object " + this.___baseElement.getIdentity().toString() + 
                            " was deleted from the database. Trying to call to " + method.getName(),
                            this.___transaction);
            }
        }
        
        // modificar el llamado
        switch (method.getName()) {
            case "___uptadeVersion":
                if (this.___objectReady) {
                    this.___uptadeVersion();
                }
                break;
            case "___injectRid":
                if (this.___objectReady) {
                    this.___injectRid();
                }
                break;
            case "___getProxiedObject":
                if (this.___objectReady) {
                    res = this.___getProxiedObject();
                }
                break;
            case "___loadLazyLinks":
                if (this.___objectReady) {
                    this.___loadLazyLinks();
                }
                break;
            case "___eagerLoad":
                if (this.___objectReady) {
                    this.___eagerLoad();
                }
                break;
            case "___fullLoad":
                if (this.___objectReady) {
                    this.___fullLoad();
                }
                break;
            case "___isDirty":
                if (this.___objectReady) {
                    res = this.___isDirty();
                }
                break;
            case "___setDirty":
                if (this.___objectReady) {
                    this.___setDirty();
                }
                break;
            case "___removeDirtyMark":
                if (this.___objectReady) {
                    this.___removeDirtyMark();
                }
                break;
            case "___commit":
                /**
                 * FIXME: se podría evitar si se controlara si los links se
                 * han cargado o no al momento de hacer el commit para
                 * evitar realizar el load sin necesidad.
                 */
                if (this.___objectReady) {
                    if (this.___loadLazyLinks) {
                        this.___loadLazyLinks();
                    }
                    this.___commit();
                }
                break;
            case "___reload":
                if (this.___objectReady) {
                    this.___reload();
                }
                break;
            case "___commitSuccessful":
                if (this.___objectReady) {
                    this.___commitSuccessful();
                }
                break;
            case "___setDeletedMark":
                this.___setDeletedMark();
                break;
            case "___updateElement":
                this.___updateElement();
                break;
            
            case "___setEdge":
                this.___setEdge((OEdge)args[0]);
                break;
            case "___setVertex":
                this.___setVertex((OVertex)args[0]);
                break;

            case "___setAuditLogLabel":
                this.___setAuditLogLabel((String)args[0]);
                break;
            case "___getAuditLogLabel":
                res = this.___getAuditLogLabel();
                break;
                
            
            case "___ogm___setDirty":
                res = superMethod.invoke(self, args);
                break;
            case "___ogm___isDirty":
                res = superMethod.invoke(self, args);
                break;

            default:
                // invoke the method on the real object with the given params:

                if (method.getName().equals("toString")) {
                    try {
                        //if object doesn't have toString defined, we implement one on the fly
                        ReflectionUtils.findMethod(this.___baseClass, "toString", (Class<?>[]) null);
                    } catch (NoSuchMethodException nsme) {
                        res = this.___baseElement.getIdentity().toString(); //returns rid
                        break;
                    }
                }

                if (this.___loadLazyLinks) {
                    boolean methodTriggersLoadLazyLink = true;
                    if (method.getName().equals("equals") || method.getName().equals("hashCode")) {
                        methodTriggersLoadLazyLink &= this.___transaction.getSessionManager().
                                getConfig().isEqualsAndHashCodeTriggerLoadLazyLinks();
                    }
                    methodTriggersLoadLazyLink &= !method.isAnnotationPresent(DontLoadLinks.class);
                    if (this.___objectReady && methodTriggersLoadLazyLink) {
                        this.___loadLazyLinks();
                    }
                }
                
                if (superMethod == null) {
                    System.out.println("superMethod == NULL !!!!");
                    return defaultValue;
                }
                try {
                    res = superMethod.invoke(self, args);
                } catch (InvocationTargetException ex) {
                        throw ex.getCause();
                }

                // verificar si hay diferencias entre los objetos dependiendo de la estrategia seleccionada.
                if (this.___objectReady) {
                    switch (this.___transaction.getSessionManager().getActivationStrategy()) {
                        case CLASS_INSTRUMENTATION:
                            // si se está usando la instrumentación de clase, directamente verificar en el objeto
                            // cual es su estado.
                            LOGGER.log(Level.FINEST, "o: {0} ITrans: {1}", new Object[]{self.getClass().getName(), self instanceof ITransparentDirtyDetector});
                            if (((ITransparentDirtyDetector) self).___ogm___isDirty()) {
                                LOGGER.log(Level.FINEST, "objeto {0} marcado como dirty por ASM. Agregarlo a la lista de pendientes.", self.getClass().getName());
                                this.___setDirty();
                            }
                    }
                }
                break;
        }
        // return the result
        LOGGER.log(Level.FINEST, "<<<<<<<<<<<<<<<<<<<<< INTERCEPT END: "+debugLabel);
        return res;
    }

SimpleVertex test object:

package test;

import java.util.Date;
import java.util.Objects;
import java.util.UUID;
import java.util.logging.Logger;
import net.odbogm.annotations.Audit;
import net.odbogm.annotations.Entity;
import net.odbogm.annotations.Ignore;
import net.odbogm.annotations.RID;
import net.odbogm.annotations.Sequence;
import net.odbogm.annotations.Version;

/**
 *
 * @author Marcelo D. Ré {@literal <marcelo.re@gmail.com>}
 */
@Entity
@Audit(log = Audit.AuditType.DELETE)
public class SimpleVertex implements Comparable<SimpleVertex>{
    @Ignore
    private final static Logger LOGGER = Logger.getLogger(SimpleVertex.class .getName());

    @RID private String rid;
    @Version private int version = -1;
    @Sequence(sequenceName = "test_sequence") private final Long serial = null;

    private String uuid;
    private String s;
    public int i;
    private float f;
    private boolean b;
    private Date fecha;
        
    private Integer oI;
    private Float oF;
    private Boolean oB;
    
    public Date getFecha() {
        return fecha;
    }

    public void setFecha(Date fecha) {
        this.fecha = fecha;
    }
    
    public int getI() {
        return i;
    }

    public float getF() {
        return f;
    }

    public boolean isB() {
        return b;
    }

    public Integer getoI() {
        return oI;
    }

    public Float getoF() {
        return oF;
    }

    public Boolean getoB() {
        return oB;
    }

    public Long getSerial() {
        return serial;
    }
    
    
    public SimpleVertex(String s, int i, float f, boolean b, Integer oI, Float oF, Boolean oB) {
        this.s = s;
        this.i = i;
        this.f = f;
        this.b = b;
        this.oI = oI;
        this.oF = oF;
        this.oB = oB;
        this.uuid = UUID.randomUUID().toString();
    }

    public SimpleVertex(){
        this.s = "string";
        this.i = 1;
        this.f = 0.1f;
        this.b = true;
        this.oI = 100;
        this.oF = 1.1f;
        this.oB = true;
        this.uuid = UUID.randomUUID().toString();
    }
    
    public SimpleVertex(String s) {
        super();
        this.s = s;
    }
    
    public String getRid() {
        return rid;
    }

    public int getVersion() {
        return version;
    }
    
    public String getS(){
        return this.s;
    }

    public void setRid(String rid) {
        this.rid = rid;
    }

    public void setS(String s) {
        this.s = s;
    }
    
    public void testSVMethod() {
        System.out.println("in SV");
    }

//    @Override
//    public String toString() {
//        return this.s + " - " + this.b +  " - " + this.i +  " - " + this.f;
//    }

    public void setI(int i) {
        this.i = i;
    }

    public void setF(float f) {
        this.f = f;
    }

    public void setB(boolean b) {
        this.b = b;
    }

    public void setoI(Integer oI) {
        this.oI = oI;
    }

    public void setoF(Float oF) {
        this.oF = oF;
    }

    public void setoB(Boolean oB) {
        this.oB = oB;
    }

    public String getUUID() {
        return this.uuid;
    }
//    @Override
//    public int hashCode() {
//        int hash = 7;
//        return hash;
//    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SimpleVertex other = (SimpleVertex) obj;
        return Objects.equals(this.uuid, other.uuid);
    }

    @Override
    public int compareTo(SimpleVertex t) {
        return this.uuid.compareTo(t.getUUID());
    }
    
}

and SimpleVertexEx test object:

package test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.logging.Logger;
import net.odbogm.annotations.Audit;
import net.odbogm.annotations.CascadeDelete;
import net.odbogm.annotations.Entity;
import net.odbogm.annotations.FieldAttributes;
import net.odbogm.annotations.Ignore;
import net.odbogm.annotations.Indexed;
import net.odbogm.annotations.RemoveOrphan;
import net.odbogm.annotations.DontLoadLinks;
import net.odbogm.annotations.Eager;
import net.odbogm.annotations.Indirect;

/**
 *
 * @author Marcelo D. Ré {@literal <marcelo.re@gmail.com>}
 */
@Entity
@Audit(log = Audit.AuditType.ALL)
public class SimpleVertexEx extends SimpleVertex {
    @Ignore
    private final static Logger LOGGER = Logger.getLogger(SimpleVertexEx.class .getName());

    @FieldAttributes(mandatory = FieldAttributes.Bool.TRUE)
    private String svex;

    private SimpleVertexEx looptest;
    
    public EnumTest enumTest;

    @Indexed(type = Indexed.IndexType.UNIQUE)
    private String svuuid;

    @RemoveOrphan
    public SimpleVertex svinner; 
    
    public List<String> lString;
    
    public ArrayList<String> alString;
    
    public Map<String, String> mString;
    
    public HashMap<String, String> hmString;
    
    @RemoveOrphan
    @CascadeDelete
    public ArrayList<SimpleVertex> alSV;
    
    public List<SimpleVertex> lSV;
    
    public ArrayList<SimpleVertexEx> alSVE;
    
    @CascadeDelete
    public HashMap<String, SimpleVertex> hmSV;
    
    public HashMap<String, SimpleVertexEx> hmSVE;
    
    public HashMap<EdgeAttrib, SimpleVertexEx> ohmSVE;
    
    @Indirect(linkName = "SimpleVertexEx_looptest")
    private SimpleVertexEx indirectLoopTest;
    
    @Eager
    private SimpleVertexEx eagerTest;
    
    @Indirect(linkName = "SimpleVertexEx_eagerTest")
    private SimpleVertexEx indirectEagerTest;
    
    @Eager
    @Indirect(linkName = "SimpleVertexEx_eagerTest")
    private SimpleVertexEx eagerIndirectEagerTest;
    
    
    public SimpleVertexEx(String svex, String s, int i, float f, boolean b, Integer oI, Float oF, Boolean oB) {
        super(s, i, f, b, oI, oF, oB);
        this.svex = svex;
        this.enumTest = EnumTest.UNO;
        this.svuuid = UUID.randomUUID().toString();
    }

    public SimpleVertexEx() {
        this(null, "default");
    }

    public SimpleVertexEx(String s) {
        this(s, "default");
    }
    
    public SimpleVertexEx(String s, String svex) {
        super(s);
        this.svex = svex;
        this.svuuid = UUID.randomUUID().toString();
    }
        
    public void initEnum() {
        this.enumTest = EnumTest.UNO;
    }

    public void initArrayListString() {
        this.alString = new ArrayList<>();
        this.alString.add("String 1");
        this.alString.add("String 2");
        this.alString.add("String 3");
    }
    
    public void initHashMapString() {
        this.hmString = new HashMap<>();
        this.hmString.put("hmString 1", "hmString 1");
        this.hmString.put("hmString 1", "hmString 2");
        this.hmString.put("hmString 1", "hmString 3");
    }
    
    
    public void initArrayList(){
        this.alSV = new ArrayList<SimpleVertex>();
        this.alSV.add(new SimpleVertex());
        this.alSV.add(new SimpleVertex());
        this.alSV.add(new SimpleVertex());
    }
    
    public void initHashMap() {
        this.hmSV = new HashMap<String, SimpleVertex>();
        SimpleVertex sv = new SimpleVertex();
        this.hmSV.put("key1", sv);
        this.hmSV.put("key2", sv);
        this.hmSV.put("key3", new SimpleVertex());
    }

    public HashMap<String, SimpleVertexEx> getHmSVE() {
        return hmSVE;
    }

    public void setHmSVE(HashMap<String, SimpleVertexEx> hmSVE) {
        this.hmSVE = hmSVE;
    }

    public HashMap<EdgeAttrib, SimpleVertexEx> getOhmSVE() {
        return ohmSVE;
    }

    public void setOhmSVE(HashMap<EdgeAttrib, SimpleVertexEx> ohmSVE) {
        this.ohmSVE = ohmSVE;
    }
    
    
    public void initInner() {
        this.svinner = new SimpleVertex();
        this.svinner.setS("sv inner");
    }
    
    public void testSVEXMethod() {
        System.out.println("in SVEx");
    }

    public void setSvinner(SimpleVertex svinner) {
        this.svinner = svinner;
    }

    public void setSvex(String s) {
        this.svex = s;
    }
    
    public String getSvex() {
        return svex;
    }

    public EnumTest getEnumTest() {
        return enumTest;
    }

    public void setEnumTest(EnumTest e) {
        this.enumTest = e;
    }
    
    public SimpleVertex getSvinner() {
        return svinner;
    }

    public ArrayList<SimpleVertex> getAlSV() {
        return alSV;
    }

    public ArrayList<SimpleVertexEx> getAlSVE() {
        return alSVE;
    }

    public void setAlSVE(ArrayList<SimpleVertexEx> alSVE) {
        this.alSVE = alSVE;
    }
    
    public HashMap<String, SimpleVertex> getHmSV() {
        return hmSV;
    }

    public SimpleVertexEx getLooptest() {
        return looptest;
    }
    
    @DontLoadLinks
    public SimpleVertexEx getLooptestLinkNotLoaded() {
        return looptest;
    }

    public void setLooptest(SimpleVertexEx looptest) {
        this.looptest = looptest;
    }

    @DontLoadLinks
    public SimpleVertexEx getEagerTest() {
        return eagerTest;
    }

    public void setEagerTest(SimpleVertexEx eagerTest) {
        this.eagerTest = eagerTest;
    }

    @DontLoadLinks
    public SimpleVertexEx getIndirectLoopTestDontLoad() {
        return indirectLoopTest;
    }
    
    public SimpleVertexEx getIndirectLoopTest() {
        return indirectLoopTest;
    }

    @DontLoadLinks
    public SimpleVertexEx getIndirectEagerTest() {
        return indirectEagerTest;
    }
    
    @DontLoadLinks
    public SimpleVertexEx getEagerIndirectEagerTest() {
        return eagerIndirectEagerTest;
    }

    public String getUuid() {
        return this.svuuid;
    }

    public void setUuid(String uuid) {
        this.svuuid = uuid;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + Objects.hashCode(this.svuuid);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!SimpleVertexEx.class.isInstance(obj)) {
            return false;
        }
        final SimpleVertexEx other = (SimpleVertexEx) obj;
        return Objects.equals(this.svuuid, other.svuuid);
    }
    
}

Now, when I use that's objects:

var res = sm.query(SimpleVertexEx.class, "where out('SimpleVertexEx_alSV').size() != 0 limit 1");

SimpleVertexEx sve = res.get(0);
        
SimpleVertex sv1 = sve.getAlSV().get(0);
SimpleVertex sv2 = sve.getAlSV().get(1);
SimpleVertex sv3 = sve.getAlSV().get(2);
        
System.out.println("sv1: "+sv1.getRid());
System.out.println("sv2: "+sv2.getRid());
System.out.println("sv3: "+sv3.getRid());
System.out.println(""+sv1.compareTo(sv2));
System.out.println(""+sv2.compareTo(sv3));
        
var falla = sve.getAlSV().stream().sorted().collect(Collectors.toList());

All the lines works but the last fail. Sort call compareTo on the sv's but the proxy get a superMethod = null. Why? In the previous lines the call work well. This is what the interceptor log:

MÁS DETALLADO[2022/08/17 10:21:34]:net.odbogm.proxy.ObjectProxy intercept :: =====================================================
MÁS DETALLADO[2022/08/17 10:21:34]:net.odbogm.proxy.ObjectProxy intercept :: test.SimpleVertex$ByteBuddy$ghrAs2Lb : #414:0 > method: compareTo  superMethod: compareTo$accessor$XL9qkaa5
MÁS DETALLADO[2022/08/17 10:21:34]:net.odbogm.proxy.ObjectProxy intercept :: =====================================================

MÁS DETALLADO[2022/08/17 11:02:21]:net.odbogm.proxy.ObjectProxy intercept :: =====================================================
MÁS DETALLADO[2022/08/17 11:02:21]:net.odbogm.proxy.ObjectProxy intercept :: test.SimpleVertex$ByteBuddy$rMJgDCTS : #413:0 > method: compareTo  superMethod: compareTo$accessor$q70euKMf
MÁS DETALLADO[2022/08/17 11:02:21]:net.odbogm.proxy.ObjectProxy intercept :: =====================================================

MÁS DETALLADO[2022/08/17 10:21:34]:net.odbogm.proxy.ObjectProxy intercept :: =====================================================
MÁS DETALLADO[2022/08/17 10:21:34]:net.odbogm.proxy.ObjectProxy intercept :: test.SimpleVertex$ByteBuddy$ghrAs2Lb : #413:0 > method: compareTo  superMethod: NULL
MÁS DETALLADO[2022/08/17 10:21:34]:net.odbogm.proxy.ObjectProxy intercept :: =====================================================
superMethod == NULL !!!!

At some point it miss the method but I could not reproduce it as a simple script.

Marcelo D. Ré
  • 181
  • 2
  • 10
  • Do you have the intercepr method that is called? I assume it's there where you configured it. – Rafael Winterhalter Aug 18 '22 at 06:04
  • Hi Rafael. I have added the intercept method. The whole project is available at github at https://github.com/mdre/odbogm/tree/ByteBuddy in the project, the net.odbogm.proxy.ObjectProxyFactory.java is called to create every object that is recovered from the database and ObjectProxy.java have all the implemented methods. – Marcelo D. Ré Aug 18 '22 at 19:34
  • Does the super class define an implementation? I assume there is none where you requested the proxy to be null. – Rafael Winterhalter Aug 21 '22 at 15:18
  • SimpleVertex and SimpleVertexEx added. The first has the compareTo implemented and is there where it fail. – Marcelo D. Ré Aug 22 '22 at 14:17
  • Well! I find something. It's seems BB is cloning two method compareTo. One is the default compareTo that is not implemented and the other is the implemented version compareTo. I suppose it is calling the first that is not implemented. How can I fix this? – Marcelo D. Ré Sep 14 '22 at 13:02
  • One would be a bridge method. What do you mean by "not implemented"? – Rafael Winterhalter Sep 15 '22 at 05:09
  • Look at SimpleVertex. The method "comparedTo(Object)" is not implemented. Te overrided version "comparedTo(SimpleVertex) is implemented. If I use: ```....method(ElementMatchers.any()).....method(ElementMatchers.isDeclaredBy(c))...``` the test fail but if I use ```....method(ElementMatchers.isDeclaredBy(ObjectProxy.class).....method(ElementMatchers.isDeclaredBy(c))...``` this test pass but other three fails with weird errors. – Marcelo D. Ré Sep 19 '22 at 17:40

2 Answers2

0

I think you annotation @SuperMethod(nullIfImpossible = true) is causing the super method to be null when the implementation for a method is not resolved. Please refer https://stackoverflow.com/a/41932172/11864540

Ajay Lamba
  • 71
  • 5
0

Finally I found a workaround. It's a ugly way but work when BB fail to found the correct method. Add this in the interceptor as a superMethod call:

...
...
try {
     if (superMethod == null) {
        String bbMName = Arrays.asList(self.getClass().getDeclaredMethods()).stream().filter(m->m.getName().startsWith(method.getName()+"$ac")).findFirst().get().getName();
        LOGGER.log(Level.FINEST, "SuperMethod NULL!!! ---> redefine superMethod> "+bbMName);
        Class[] p = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            p[i] = args[i].getClass().getName().contains("$ByteBuddy")?args[i].getClass().getSuperclass():args[i].getClass();
        }
                    
        LOGGER.log(Level.FINEST, "Method parameterTypes: " + Arrays.asList(method.getParameterTypes()));
        LOGGER.log(Level.FINEST, "Args parameterTypes: " + Arrays.asList(p));
        Method m = self.getClass().getMethod(bbMName, p);
        res = m.invoke(self, args);
     } else {
        res = superMethod.invoke(self, args);
     }
} catch (InvocationTargetException ex) {
     throw ex.getCause();
}
Marcelo D. Ré
  • 181
  • 2
  • 10