如何使用ByteBuddy代理处理构造函数抛出的异常?

jmmurillo:

我试图使用ByteBuddy(v1.7.9)Java代理记录在方法和构造函数中抛出的每个调用,返回的对象和异常,而不会影响已检测代码的正常功能。

我当前代理的实例是

new AgentBuilder.Default()
                .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
                .type((typeDescription, classLoader, module, classBeingRedefined, protectionDomain) -> 
                     matcher.matchesIncoming(typeDescription.getTypeName()))
                .transform((builder, typeDescription, classLoader, javaModule) -> builder
                        .visit(Advice.to(CustomAdvicer.class).on(ElementMatchers.any())))
                .installOn(inst);

我从最简单的“顾问”开始,

public class CustomAdvicer {
    @Advice.OnMethodEnter
    public static void enter(@Advice.Origin String origin) {
        System.out.println("Entering " + origin);
    }

    @Advice.OnMethodExit(onThrowable = Throwable.class)
    public static void exit(
        @Advice.Return(typing = Assigner.Typing.DYNAMIC) @RuntimeType Object value,
        @Advice.Origin String origin,
        @Advice.Thrown Throwable thrown) {
        System.out.println("Exiting " + origin);
    }
}

但是,当我运行该程序时,我从bytebuddy中得到了一个例外:

[Byte Buddy] ERROR some.pack.Thrower [sun.misc.Launcher$AppClassLoader@18b4aac2, null, loaded=false]
java.lang.IllegalStateException: Cannot catch exception during constructor call for public some.pack.Thrower() throws java.lang.Exception
    at net.bytebuddy.asm.Advice.doWrap(Advice.java:515)
    at net.bytebuddy.asm.Advice.wrap(Advice.java:470)
    at net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$Entry.wrap(AsmVisitorWrapper.java:481)
    at net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$DispatchingVisitor.visitMethod(AsmVisitorWrapper.java:562)
    at net.bytebuddy.jar.asm.ClassVisitor.visitMethod(ClassVisitor.java:327)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$RedefinitionClassVisitor.visitMethod(TypeWriter.java:3801)
    at net.bytebuddy.jar.asm.ClassReader.readMethod(ClassReader.java:1020)
    at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:698)
    at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:500)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:2941)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1633)
    at net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder.make(RebaseDynamicTypeBuilder.java:200)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$Transformation$Simple$Resolution.apply(AgentBuilder.java:8905)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:9306)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:9269)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1300(AgentBuilder.java:9047)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmDispatcher.run(AgentBuilder.java:9625)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$LegacyVmDispatcher.run(AgentBuilder.java:9575)
    at java.security.AccessController.doPrivileged(Native Method)
    at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:9194)
    at sun.instrument.TransformerManager.transform(Unknown Source)
    at sun.instrument.InstrumentationImpl.transform(Unknown Source)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at Main.main(Main.java:23)

因此,牢记它一定不会干扰原始代码我该怎么做才能记录在构造函数中引发的异常

顺便说一下,Thrower类是我为测试此情况而编写的一个愚蠢的类:

package some.pack;

public class Thrower {
  public Thrower() throws Exception {
    throw new Exception("By courtesy of thrower! ;)");
  }
}
拉斐尔·温特豪德(Rafael Winterhalter):

问题在于构造函数有一个隐式的第一条指令,该指令是另一个或超级构造函数的调用。您的Thrower课程确实看起来像这样:

public class Thrower {
  public Thrower() throws Exception {
    super();
    throw new Exception("By courtesy of thrower! ;)");
  }
}

如果要将整个调用包装在try-catch块中,将产生以下结果:

public class Thrower {
  public Thrower() throws Exception {
    try {
      super();
      throw new Exception("By courtesy of thrower! ;)");
    } catch (Exception e) {
      ...
    }
  }
}

但这在JVM中是不合法的,因此Byte Buddy不允许这样做。没有什么方法可以排除超级构造函数调用,因为这是第一次调用只是一种Java语言约定,而字节码则允许更多任意组合。由于您不知道类来自哪种语言,因此Byte Buddy在这里不尝试任何技巧,而根本不允许这样做。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用代理处理HTTPS连接请求

使用 WKWebView 代理处理 HTTP 请求

如何断言构造函数中抛出的异常?

构造函数抛出异常

从构造函数抛出异常?

如何使用ByteBuddy创建默认构造函数?

如何在Netty Client(4.1)中使用Socks4 / 5代理处理程序

如果构造函数抛出异常,如何删除对象?

当网络边缘的构造函数抛出异常时,避免使用SIGTRAP

如何使用基于 C# 中自定义异常构造的函数抛出自定义异常?

如何使用明确构造的任务处理异常

代理处理程序函数中[] byte的字符串表示形式

如何从构造函数中捕获异常而不处理整个函数?

C ++,处理构造函数的异常

构造函数中的异常处理

在代理处理程序中,如何区分获取属性(var)与调用方法?

使用自定义NSURLProtocol和HTTP代理处理重定向

如果构造函数抛出异常会怎样?

使用最终成员处理构造函数中捕获的Java异常

如何使用ByteBuddy获取类的动态代理

如何使用ByteBuddy创建动态代理

未处理ArgumentOutOfRangeException(从Form构造函数抛出)

使用SpreadsheetApp.openById()时如何处理抛出的异常

如何检测构造函数是否为带有抛出析构函数的异常

如何指定类构造函数的返回类型(例如使用代理)?

ByteBuddy 如何使用构造函数调用类中的另一个构造函数来创建类?

如何使用`with-redefs`总是抛出函数异常

如何使用Moq为异步函数抛出异常

Golang gin 代理处理苗条的前端和 Golang api