如何分析由忽略的ExceptionInInitializerError导致的NoClassDefFoundError? [英] How to analyse a NoClassDefFoundError caused by an ignored ExceptionInInitializerError?

查看:192
本文介绍了如何分析由忽略的ExceptionInInitializerError导致的NoClassDefFoundError?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我在下午分析了一个NoClassDefFoundError。在一次又一次验证类路径之后,原来,有一个类的静态成员抛出了第一次被忽略的异常。之后,每次使用该类时都会抛出一个没有意义的堆栈跟踪的NoClassDefFoundError:

Today I spent my afternoon with analysing a NoClassDefFoundError. After verifying the classpath again and again, it turned out that there was a static member of a class that threw an Exception that was ignored the first time. After that every use of the class throw a NoClassDefFoundError without a meaningful stacktrace:

Exception in thread "main" java.lang.NoClassDefFoundError: 
    Could not initialize class InitializationProblem$A
    at InitializationProblem.main(InitializationProblem.java:19)

就是这样。

public class InitializationProblem {
    public static class A {
        static int foo = 1 / 0;
        static String getId() {
            return "42";
        }
    }

    public static void main( String[] args ) {
        try {
            new A();
        }
        catch( Error e ) {
            // ignore the initialization error
        }

        // here an Error is being thrown again,
        // without any hint what is going wrong.
        A.getId();
    }
}

为了使它不那么容易,除了最后调用 A.getId()隐藏在一个非常大的项目的初始化代码的某个地方。

To make it not so easy, all but the last call of A.getId() was hidden somewhere in the initialization code of a very big project.

现在,我在试用和错误的几个小时后发现这个错误,我想知道是否有一个直接的方法来从抛出的异常开始找到这个bug 。

Now that I've found this error after hours of trial and error, I'm wondering if there is a straight forward way to find this bug starting from the thrown exception. Any ideas on how to do this?

我希望这个问题将是一个提示任何人分析一个莫名其妙的 NoClassDefFoundError

I hope this question will be a hint for anyone else analysing an inexplicable NoClassDefFoundError.

推荐答案

我的建议是通过避免静态初始化器尽可能避免这个问题。因为这些初始化器在类加载过程中被执行,许多框架不能很好的处理它们,而且实际上老的VM也不会很好地处理它们。

My advice would be to avoid this problem by avoiding static initializers as much as you can. Because these initializers get executed during the classloading process, many frameworks don't handle them very well, and in fact older VMs don't handle them very well either.

(如果不是全部)静态初始化器可以重构成其他形式,一般来说,它使问题更容易处理和诊断。正如您所发现的,静态初始化程序被禁止抛出已检查的异常,因此您必须进行日志和忽略,或者不加注销并重新启动,这些都不会使得诊断工作变得更容易。

Most (if not all) static initializers can be refactored into other forms, and in general it makes the problems easier to handle and diagnose. As you've discovered, static initializers are forbidden from throwing checked exceptions, so you've got to either log-and-ignore, or log-and-rethrow-as-unchecked, none of which make the job of diagnosis any easier.

此外,大多数类加载器使一次性尝试加载给定的类,如果第一次失败,并且处理不当,问题得到有效的压制,最终导致泛型错误,很少或没有上下文。

Also, most classloaders make one-and-only-one attempt to load a given class, and if it fails the first time, and isn't handled properly, the problem gets effectively squashed, and you end up with generic Errors being thrown, with little or no context.

这篇关于如何分析由忽略的ExceptionInInitializerError导致的NoClassDefFoundError?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆