Java ByteBuddy拦截的方法未被调用
Java ByteBuddy拦截的方法未被调用,java,hook,byte-buddy,Java,Hook,Byte Buddy,private void orsc.orscaplet.draw()绘制视频游戏的每一帧。我们的目标是拦截draw()方法,这样我们就可以在当前绘制的帧上绘制,这样我们就可以显示用户通常看不到的信息 下面,我使用ByteBuddy创建orsc.orscaplet的一个新子类,然后截取draw()函数,使其正常调用draw(),并调用public void PaintCallback.paint() 视频游戏的main()位于orsc.OpenRSC内。因此,我们将使用带有截获方法的类加载器创建一
private void orsc.orscaplet.draw()
绘制视频游戏的每一帧。我们的目标是拦截draw()
方法,这样我们就可以在当前绘制的帧上绘制,这样我们就可以显示用户通常看不到的信息
下面,我使用ByteBuddy创建orsc.orscaplet
的一个新子类,然后截取draw()
函数,使其正常调用draw()
,并调用public void PaintCallback.paint()
视频游戏的main()
位于orsc.OpenRSC
内。因此,我们将使用带有截获方法的类加载器创建一个新的orsc.OpenRSC
对象:
Class loadedMyClass = myLoader.loadClass("orsc.OpenRSC");
Constructor constructor = loadedMyClass.getConstructor();
Object myClassObject = constructor.newInstance();
return myClassObject; //later on, we call orsc.OpenRSC.main() with this object.
但是,我没有收到任何调用PaintCallback.paint()
。为什么我的截取不起作用?我有三个理论:
myLoader
类加载器,该类仍在其他地方加载。但是,我尝试过使用ByteBuddyAgent.install()
,并在.load(myLoader,ClassLoadingStrategy.fromInstalledAgent())中指定了它
,而不是执行子类
?如果是这样,如果我使用重定义截取,我可以调用原始函数吗?如果是,怎么做?我尝试了很多不同的方法,结果我的轮子在泥里转得很厉害
子类
或重定义
,而是重基
?我尝试使用以下代码执行此操作,并从instrumentation库收到异常:
new ByteBuddy().rebase(orsc.ORSCApplet.class)
.method(ElementMatchers.named("draw"))
.intercept(SuperMethodCall.INSTANCE.andThen(MethodCall.invoke(PaintCallback.class.getMethod("paint"))))
.make()
.load(myLoader,
ClassReloadingStrategy.fromInstalledAgent());
java.lang.IllegalStateException: Error invoking java.lang.instrument.Instrumentation#retransformClasses
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:503)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$2.apply(ClassReloadingStrategy.java:568)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:225)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:100)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6292)
at reflector.Reflector.injectCallbacksAndReturnClient(Reflector.java:319)
at reflector.Reflector.createClient(Reflector.java:50)
at bot.Main.main(Main.java:164)
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:495)
... 7 more
创建子类时,必须确保该子类在创建时返回,通常是从某种工厂返回。否则,您的子类将存在,但永远不会被使用。我不清楚您是否在代码中这样做 重定基可被视为子类化,其中原始类在其内部进行扩展,以避免从代理中进行子类化的限制,因为创建工厂通常比较困难。但是,这通常需要添加方法或字段,而在类已经加载时,即使使用Java代理,也不可能添加这些方法或字段。但是,在您的情况下,如果避免引用
orsc.orscaplet.class
,则可以使用TypePool.Default
创建描述,并将其提供给Byte Buddy。如果然后通过注入加载插入的类,它将位于原始类文件之前,并在应用程序中使用
然而,最优雅的方法是使用重新定义,它可以应用于加载的类。通常,您会为此使用
AgentBuilder
。如果要向现有方法添加代码,最好使用建议,而不是此处的委托,因为建议会将代码添加到方法的开头和/或结尾。请确保使用DynamicType.Builder::visit
将建议作为装饰应用,而不是常规的拦截。嘿,Rafael,谢谢你的回答,谢谢你制作了这么棒的库!
new ByteBuddy().rebase(orsc.ORSCApplet.class)
.method(ElementMatchers.named("draw"))
.intercept(SuperMethodCall.INSTANCE.andThen(MethodCall.invoke(PaintCallback.class.getMethod("paint"))))
.make()
.load(myLoader,
ClassReloadingStrategy.fromInstalledAgent());
java.lang.IllegalStateException: Error invoking java.lang.instrument.Instrumentation#retransformClasses
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:503)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$2.apply(ClassReloadingStrategy.java:568)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:225)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:100)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6292)
at reflector.Reflector.injectCallbacksAndReturnClient(Reflector.java:319)
at reflector.Reflector.createClient(Reflector.java:50)
at bot.Main.main(Main.java:164)
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Dispatcher$ForJava6CapableVm.retransformClasses(ClassReloadingStrategy.java:495)
... 7 more