使用Byte Buddy的仪器问题

use*_*817 4 java bytecode agent byte-buddy

我让Byte Buddy作为代理运行并且它成功地拦截了我的绝大部分代码库,顺便说一句,它是相当大的代码库!虽然有一些异常值我无法检测,我在下面记录了这些异常值,希望你能知道答案!

1. CGLIB生成的类

Spring生成一些额外的类,这些类与我的类具有相同的名称,但是"$$EnhancerByCGLIB$$"附加到末尾并且这些类导致错误.我得到的错误是:

java.lang.IllegalStateException: Cannot resolve type description for com.mycompany.MySpringBean$$EnhancerByCGLIB$$ee9d3c37_2
at net.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:152)
at net.bytebuddy.pool.TypePool$LazyFacade$LazyResolution$LazyTypeDescription.resolve(TypePool.java:3158)
at net.bytebuddy.pool.TypePool$LazyFacade$LazyResolution$LazyTypeDescription.getModifiers(TypePool.java:3238)
at net.bytebuddy.ByteBuddy.rebase(ByteBuddy.java:697)
Run Code Online (Sandbox Code Playgroud)

事实上,我没有兴趣检测CGLIB生成的类,因此希望排除这些.什么是最好的方法?目前,我按名称匹配,但我想知道这是否是最佳方式.

.and(not(nameContains("EnhancerByCGLIB")))
Run Code Online (Sandbox Code Playgroud)

2.打包私有和私有类

我看到的另一个问题是检测a package private或a private class.

Package private 代码看起来像这样:

abstract class BaseBean {
    Object methodA(final String customerNumber){}
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

Caused by: java.lang.IllegalAccessException:
    Class net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField cannot 
    access a member of class com.mycompany.BaseBean with modifiers "public static"
Run Code Online (Sandbox Code Playgroud)

Private class 代码看起来像这样:

public class Object A {
 //variables & methods...
 private class ObjectB {}
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

Caused by: java.lang.IllegalAccessException:
    Class net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField cannot 
    access a member of class com.mycompany.ObjectA$ObjectB with modifiers "public static"
Run Code Online (Sandbox Code Playgroud)

By Byte Buddy乐器package private还是private classes

3.沉默失败

这只是一个普遍的问题,但是有可能指示Byte Buddy在每个课堂上默默地失败吗?这样,任何此类错误都不会阻止应用程序启动或Byte Buddy尽可能多地进行检测.

4.公共抽象类中的公共方法

我的代码是这样的:

package com.mycompany;
public interface InterfaceA{
    Object provideAccess(final String id);
}

package com.mycompany;
public abstract class BaseBeanA implements InterfaceA { 
  //some general helper methods
}

package com.mycompany;
public abstract class BaseBeanB extends BaseBeanA { 
    //some specific helper methods
}

package com.mycompany;
public class BeanImpl extends BaseBeanB {   
    protected Object provideAccess(final String id) {
    }
}
Run Code Online (Sandbox Code Playgroud)

这会导致在检测BaseBeanB时出现以下错误:

java.lang.IllegalArgumentException:[protected void java.lang.Object.finalize()throws java.lang.Throwable,public final native void java.lang.Object.wait(long)throws java.lang.InterruptedException,public final void java.lang.Object.wait()抛出java.lang.InterruptedException,public final void java.lang.Object.wait(long,int)throws java.lang.InterruptedException,public boolean java.lang.Object.equals(java .lang.Object),public java.lang.String java.lang.Object.toString(),public native int java.lang.Object.hashCode(),public final native java.lang.Class java.lang.Object.getClass (),protected native java.lang.Object java.lang.Object.clone()抛出java.lang.CloneNotSupportedException,public final native void java.lang.Object.notify(),public final native void java.lang.Object. notifyAll(),public java.lang.Object com.mycompany.MyInterceptor.intercept(java.util.concurrent.Callable,java.lang.Object [],java.lang.reflect.Method,java.lang.Class)抛出java .lang.Exception]允许 for public abstract Object com.mycompany.InterfaceA.provideAccess(java.lang.String)

Raf*_*ter 5

1. CGLIB生成的类

你的解决方案是对的.事实上,通过名称指定类对性能总是有好处的.例如,如果您可以排除整个包,Byte Buddy可能已经丢弃了一个类,甚至没有解析类文件,因为名称可以单独使用.

cglib生成的类的检测失败的原因是这些类没有可用的字节代码.

2.包私人和私人课程

你在这里发现了一个错误.我最近重构了这个逻辑,通过将它们公开来不要求合成字段的可访问性,但我只是忘记了包私有字段.这在主分支上修复,将以0.7-rc7发布.

3.沉默失败

如果检测失败,则始终向该报告发生此故障AgentBuilder.Listener.除此之外,失败对ClassFileTransformerAPI 没有影响.你观察到通过的任何例外吗?您可能还想查看监听器AgentBuilder被重构的最新版本.

4.公共抽象类中的公共方法

你的拦截器定义了一个类型的参数Callable,我假设它是注释的SuperCall.这会注入一个代理来调用截获方法的super方法(如果存在).对于像你试图拦截的抽象方法,这不起作用,Byte Buddy决定你的拦截器不可绑定.因此,抛出异常.

这样说,通过从委托中排除Object类型的方法,Byte Buddy不会将它们视为委托.这提高了性能.