java.lang.reflect.Proxy:巨大的异常堆栈跟踪

德拉甘·博扎诺维奇(Dragan Bozanovic)

这是一个简单的Java应用程序:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {

    interface MyInterface {
        void myMethod();
    }

    public static void main(String[] args) {
        MyInterface myInterface = (MyInterface) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[] {MyInterface.class},
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return method.invoke(proxy, args);
                }
            });
        myInterface.myMethod();
    }
}

我希望StackOverflowError这里变得简单,因为我递归地在代理实例上调用了相同的方法。

但是,异常产生的堆栈跟踪包含数百万行和数百MB的大小。

堆栈跟踪的第一部分开始如下:

java.lang.reflect.UndeclaredThrowableException
    at $Proxy0.myMethod(Unknown Source)
    at Main.main(Main.java:22)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at Main$1.invoke(Main.java:18)
    ... 2 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at $Proxy0.myMethod(Unknown Source)
    ... 7 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at Main$1.invoke(Main.java:18)
    ... 8 more

并扩展到:

Caused by: java.lang.reflect.UndeclaredThrowableException
    at $Proxy0.myMethod(Unknown Source)
    ... 1022 more

然后遵循数百万行,例如:

Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at Main$1.invoke(Main.java:18)
    at $Proxy0.myMethod(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at Main$1.invoke(Main.java:18)
    .......

和:

Caused by: java.lang.reflect.UndeclaredThrowableException
    at $Proxy0.myMethod(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at Main$1.invoke(Main.java:18)
    at $Proxy0.myMethod(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at Main$1.invoke(Main.java:18)
    .......

最后打印的行是(在上述重复序列之后):

Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"

我怀疑堆栈跟踪生成机制正在代理实例上调用某些方法(可能toString是打印它,或进行其他操作),从而一遍又一遍地重复递归(因为代理上的每个方法调用都会导致无限递归),但是代理方法执行的总数为1919(通过增加InvocationHandler.invoke方法中的计数器来衡量)。

在我的实际用例中,我当然解决了无限递归问题。我只是好奇是否有人知道这是错误还是有合理的解释?

Java版本:

java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

编辑

@JiriTousek和@AndrewWilliamson友好地分析了可能的原因。我根据他们的输入进行了模拟:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;

public class Test {
    private static int counter = 0;

    public static void main(String[] args) {
        proxy();
    }

    private static void proxy() {
        try {
            methodInvoke();
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    private static void methodInvoke() throws InvocationTargetException {
        try {
            myMethod();
        } catch (Throwable e) {
            throw new InvocationTargetException(e);
        }
    }

    private static void myMethod() {
        if (counter++ == 5) {
            throw new StackOverflowError();
        }
        proxy();
    }
}

这将导致以下堆栈跟踪:

Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
    at Test.proxy(Test.java:16)
    at Test.main(Test.java:9)
Caused by: java.lang.reflect.InvocationTargetException
    at Test.methodInvoke(Test.java:24)
    at Test.proxy(Test.java:14)
    ... 1 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at Test.proxy(Test.java:16)
    at Test.myMethod(Test.java:32)
    at Test.methodInvoke(Test.java:22)
    ... 2 more
Caused by: java.lang.reflect.InvocationTargetException
    at Test.methodInvoke(Test.java:24)
    at Test.proxy(Test.java:14)
    ... 4 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at Test.proxy(Test.java:16)
    at Test.myMethod(Test.java:32)
    at Test.methodInvoke(Test.java:22)
    ... 5 more
Caused by: java.lang.reflect.InvocationTargetException
    at Test.methodInvoke(Test.java:24)
    at Test.proxy(Test.java:14)
    ... 7 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at Test.proxy(Test.java:16)
    at Test.myMethod(Test.java:32)
    at Test.methodInvoke(Test.java:22)
    ... 8 more
Caused by: java.lang.reflect.InvocationTargetException
    at Test.methodInvoke(Test.java:24)
    at Test.proxy(Test.java:14)
    ... 10 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at Test.proxy(Test.java:16)
    at Test.myMethod(Test.java:32)
    at Test.methodInvoke(Test.java:22)
    ... 11 more
Caused by: java.lang.reflect.InvocationTargetException
    at Test.methodInvoke(Test.java:24)
    at Test.proxy(Test.java:14)
    ... 13 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at Test.proxy(Test.java:16)
    at Test.myMethod(Test.java:32)
    at Test.methodInvoke(Test.java:22)
    ... 14 more
Caused by: java.lang.reflect.InvocationTargetException
    at Test.methodInvoke(Test.java:24)
    at Test.proxy(Test.java:14)
    ... 16 more
Caused by: java.lang.StackOverflowError
    at Test.myMethod(Test.java:30)
    at Test.methodInvoke(Test.java:22)
    ... 17 more

因此,每个堆栈帧没有行号增长。

德拉甘·博扎诺维奇(Dragan Bozanovic)

当相同迹线的深度大于1024(默认值)时,打印的堆栈迹线不会被截断这就是为什么最后一个截断的跟踪以结尾... 1022 more而所有后续的跟踪都被完整打印的原因。

可以通过将MaxJavaStackTraceDepthJVM参数设置为所需值来更改默认值。当我使用Proxy来运行时,为原始示例增加它-XX:MaxJavaStackTraceDepth=8192,整个打印的堆栈跟踪下降到大约12500行,结尾为:

Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at Main1$1.invoke(Main1.java:16)
    ... 7003 more
Caused by: java.lang.reflect.UndeclaredThrowableException
    at $Proxy0.myMethod(Unknown Source)
    ... 7007 more

Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"

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

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

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

javafx中的java.lang.reflect.InvocationTargetException中的异常

来自分类Dev

错误yarn.ApplicationMaster:用户类引发异常:java.lang.reflect.InvocationTargetException java.lang.reflect.InvocationTargetException

来自分类Dev

错误yarn.ApplicationMaster:用户类引发异常:java.lang.reflect.InvocationTargetException java.lang.reflect.InvocationTargetException

来自分类Dev

JavaFX:线程“ JavaFX Application Thread”中的异常java.lang.RuntimeException:java.lang.reflect.InvocationTargetException

来自分类Dev

Android中的java.lang.reflect.invocationtargetException

来自分类Dev

java.lang.reflect.Array的性能

来自分类Dev

Roboelectric java.lang.RuntimeException:java.lang.reflect.InvocationTargetException

来自分类常见问题

线程“主”中的异常java.lang.UnsatisfiedLinkError:'void org.lwjgl.opengl.WindowsDisplay.setWindowProc(java.lang.reflect.Method)'

来自分类Dev

呼吁java.lang.reflect.Proxy对象扩展功能时科特林奇怪的行为

来自分类Dev

应用程序启动方法java.lang.reflect.InvocationTargetException中的异常

来自分类Dev

应用程序构造函数java.lang.reflect.InvocationTargetException中的JavaFX异常

来自分类Dev

BigSheets-java.io.IOException:java.lang.reflect.UndeclaredThrowableException

来自分类Dev

为什么显示“ java.lang.reflect.InvocationTargetException”

来自分类Dev

使用java.lang.reflect.Type检查实例

来自分类Dev

了解java.lang.reflect.InvocationHandler的invoke方法的“代理”参数

来自分类Dev

Scala TypeTag到java.lang.reflect.Type

来自分类Dev

显示错误原因:java.lang.reflect.InvocationTargetException

来自分类Dev

了解java.lang.reflect.InvocationHandler的invoke方法的“代理”参数

来自分类Dev

如何从Scala类型获取java.lang.reflect.Type?

来自分类Dev

Javassist:将CtMethod转换为java.lang.reflect.Method

来自分类Dev

获取java.lang.reflect.Type的简单代码

来自分类Dev

从TextField获取值时java.lang.reflect.InvocationTargetException-Javafx

来自分类Dev

java.lang.NoClassDefFoundError:scala / reflect / api / TypeCreator

来自分类Dev

什么是`4161`在java.lang.reflect.Method中修改的平均

来自分类Dev

投java.lang.reflect.Method中的功能接口

来自分类Dev

会议室DB:java.lang.reflect.InvocationTargetException

来自分类Dev

如何修复/解决java.lang.reflect.InvocationTargetException

来自分类Dev

签名的jar抛出java.lang.reflect.InvocationTargetException

来自分类Dev

如何在Maven中解决java.lang.reflect.InvocationTargetException

Related 相关文章

  1. 1

    javafx中的java.lang.reflect.InvocationTargetException中的异常

  2. 2

    错误yarn.ApplicationMaster:用户类引发异常:java.lang.reflect.InvocationTargetException java.lang.reflect.InvocationTargetException

  3. 3

    错误yarn.ApplicationMaster:用户类引发异常:java.lang.reflect.InvocationTargetException java.lang.reflect.InvocationTargetException

  4. 4

    JavaFX:线程“ JavaFX Application Thread”中的异常java.lang.RuntimeException:java.lang.reflect.InvocationTargetException

  5. 5

    Android中的java.lang.reflect.invocationtargetException

  6. 6

    java.lang.reflect.Array的性能

  7. 7

    Roboelectric java.lang.RuntimeException:java.lang.reflect.InvocationTargetException

  8. 8

    线程“主”中的异常java.lang.UnsatisfiedLinkError:'void org.lwjgl.opengl.WindowsDisplay.setWindowProc(java.lang.reflect.Method)'

  9. 9

    呼吁java.lang.reflect.Proxy对象扩展功能时科特林奇怪的行为

  10. 10

    应用程序启动方法java.lang.reflect.InvocationTargetException中的异常

  11. 11

    应用程序构造函数java.lang.reflect.InvocationTargetException中的JavaFX异常

  12. 12

    BigSheets-java.io.IOException:java.lang.reflect.UndeclaredThrowableException

  13. 13

    为什么显示“ java.lang.reflect.InvocationTargetException”

  14. 14

    使用java.lang.reflect.Type检查实例

  15. 15

    了解java.lang.reflect.InvocationHandler的invoke方法的“代理”参数

  16. 16

    Scala TypeTag到java.lang.reflect.Type

  17. 17

    显示错误原因:java.lang.reflect.InvocationTargetException

  18. 18

    了解java.lang.reflect.InvocationHandler的invoke方法的“代理”参数

  19. 19

    如何从Scala类型获取java.lang.reflect.Type?

  20. 20

    Javassist:将CtMethod转换为java.lang.reflect.Method

  21. 21

    获取java.lang.reflect.Type的简单代码

  22. 22

    从TextField获取值时java.lang.reflect.InvocationTargetException-Javafx

  23. 23

    java.lang.NoClassDefFoundError:scala / reflect / api / TypeCreator

  24. 24

    什么是`4161`在java.lang.reflect.Method中修改的平均

  25. 25

    投java.lang.reflect.Method中的功能接口

  26. 26

    会议室DB:java.lang.reflect.InvocationTargetException

  27. 27

    如何修复/解决java.lang.reflect.InvocationTargetException

  28. 28

    签名的jar抛出java.lang.reflect.InvocationTargetException

  29. 29

    如何在Maven中解决java.lang.reflect.InvocationTargetException

热门标签

归档