Java ByteBuddy-重新设置本机方法的基址

Java ByteBuddy-重新设置本机方法的基址,java,byte-buddy,Java,Byte Buddy,我正在检查是否可以使用ByteBuddy将一些庞大的ASM代码替换为更小、更优雅的解决方案。其中一部分是“包装”本机方法,这意味着在类中为任何现有的本机方法添加前缀,并提供一个新的非本机方法,该方法使用相同的名称和签名来调用前缀方法。所有这些都可以在构建期间发生,所以我不需要任何代理,也不需要担心潜在的类模式更改,等等 从文档中可以看出,ByteBuddy留下了原始方法的一个副本,并提供了通过@SuperCall调用它的可能性,这似乎是一个重定基调的例子 除了不能影响原始方法的新名称(它们需要有

我正在检查是否可以使用ByteBuddy将一些庞大的ASM代码替换为更小、更优雅的解决方案。其中一部分是“包装”本机方法,这意味着在类中为任何现有的本机方法添加前缀,并提供一个新的非本机方法,该方法使用相同的名称和签名来调用前缀方法。所有这些都可以在构建期间发生,所以我不需要任何代理,也不需要担心潜在的类模式更改,等等

从文档中可以看出,ByteBuddy留下了原始方法的一个副本,并提供了通过
@SuperCall
调用它的可能性,这似乎是一个重定基调的例子

除了不能影响原始方法的新名称(它们需要有前缀,而不是后缀)之外,以下代码还导致以下错误:

        new ByteBuddy()
        .rebase(typePool.describe("test.ClassWithNatives").resolve(), ClassFileLocator.ForClassLoader.ofClassPath())
        .method(named("someNativeMethod"))
        .intercept(MethodDelegation.to(NativeInterceptor.class))
        .make()
        .load(getClass().getClassLoader())
        .getLoaded();


有可能用ByteBuddy实现这样的场景吗

这只有通过
工具使用Java代理才能实现。否则,JVM不知道如何重新设置本机方法的基础,因为本机方法具有必须遵循方法命名约定的本机适配器。为了让Byte Buddy正常工作,原始代码被移动到一个不同的方法,以便可以从原始方法调用,否则这是不可能的

使用Java代理,可以运行:

new AgentBuilder.Default()
  .enableNativeMethodPrefix("foo")
  .type(named("test.ClassWithNatives"))
  .transform((b,t,c,m) -> b
    .method(named("someNativeMethod"))
    .intercept(MethodDelegation.to(NativeInterceptor.class))
  ).installOn(inst);

也许我遗漏了什么,但对我来说,这会导致同样的错误。我增强了lambda以获取
ReceiverTypeDefinition
,并在返回定义之前将
字节[]
保存在一个文件中。从字节码中,我看到
native
标志从类的修饰符列表中删除,但没有向
拦截器添加任何代码。此外,不存在重命名的本机方法(除此之外,交给ByteBuddy的本机方法前缀似乎仅用于在检测上设置,但并不真正影响ByteBuddy如何生成新方法名称,是吗?)您是对的,我在这里发现了一个bug,我正在版本1.6.6中解决。我会在接下来的几个小时内推它。很好,我刚刚重新测试过。现在和代理一起工作!另外,通过
newbytebuddy()
本机方法现在被正确截获,只是我显然无法调用原始方法,因为它没有前缀。不确定它是否会破坏体系结构,但使用类似于
newbytebuddy()的东西是否“错误”。enabletivemethodprefix(“前缀”)
?另外,如果您能分享一些关于如何调用带前缀的本机的见解,我将不胜感激,因为我无法找到使用
javap
的本机方法,而只是
invokestatic
它。但是现在定义的方法在哪里呢?本机方法前缀是通过Java的
Instrumentation
接口发送的,而
ByteBuddy
实例不会直接与之交互。通过只在rebase方法前面加前缀(这可以通过重载的
rebase
方法实现),本地方法不再正确绑定,因为它们的名称已更改。因此,前缀是通过插装绑定的,我的意思是在转换的类中根本看不到本机方法。我可以看到带有原始名称的重基方法,它不再是本机的(正如预期的那样),但是我找不到名称中带有前缀的新本机方法。我唯一看到的是一条invokestatic指令,它指向一个带有前缀名称的方法(这也是预期的)。但是使用javap,在转换后的类中不再显示本机方法。尽管如此,它还是可以工作,但是如果字节码中没有本机代码,我真的不知道jvm在调用什么。我错过了什么?
new AgentBuilder.Default()
  .enableNativeMethodPrefix("foo")
  .type(named("test.ClassWithNatives"))
  .transform((b,t,c,m) -> b
    .method(named("someNativeMethod"))
    .intercept(MethodDelegation.to(NativeInterceptor.class))
  ).installOn(inst);