使用Byte Buddy进行检测的问题

时间:2015-10-29 11:18:20

标签: 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)

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

.and(not(nameContains("EnhancerByCGLIB")))

2。包私人和私人课程

我看到的另一个问题是检验package privateprivate class

Package private代码如下所示:

abstract class BaseBean {
    Object methodA(final String customerNumber){}
}

我得到的错误是:

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

Private class代码如下所示:

public class Object A {
 //variables & methods...
 private class ObjectB {}
}

我得到的错误是:

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"

Byte Buddy乐器package privateprivate 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) {
    }
}

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

  

java.lang.IllegalArgumentException:[protected void   java.lang.Object.finalize()抛出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(),受保护的本机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中)   throws java.lang.Exception]允许从公共抽象派生   对象com.mycompany.InterfaceA.provideAccess(java.lang.String)

1 个答案:

答案 0 :(得分:5)

<强> 1。 CGLIB生成了类

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

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

<强> 2。包私人和私人课程

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

第3。沉默失败

如果检测失败,则始终向AgentBuilder.Listener报告此失败。除此之外,失败没有效果,因为ClassFileTransformer API暗示了这一点。你观察到通过的任何例外吗?您可能还想查看侦听器AgentBuilder被重构的最新版本。

<强> 4。公共抽象类中的公共方法

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

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