NoClassDefFound Error

前两天碰到一个奇怪的问题,异常的信息就是NoClassDefFoundError,但是需要加载的类肯定是可以找得到的,最后问题的根源在于内存不足,由于产品需要加载的类非常的多,到现在我们的maxPermSize已经需要设置为128m了,而那个错误就是由于内存不足,类初始化的时候内存不足无法初始化成功导致出现NoClassDefFoundError,这个就让我联想到原来经常遇到的类实例初始化的异常,最终报的错也是NoClassDefFoundError,呵呵,所以,以后遇到这个异常要仔细看看后面的详细异常信息,如果是<clinit>抛出的,基本上就是初始化失败而不是真正的找不到类定义了。

今天在看深入Java虚拟机的class文件结构时,看到了这么一句话,

可能出现在class文件中的两种编译器产生的方法是:实例初始化方法(名为<init>)和类与接口初始化方法(名为<clinit>)。



这两种方法有什么区别呢?

首先:这两个方法一个是虚拟机在装载一个类初始化的时候调用的(clinit)。另一个是在类实例化时调用的(init)



首先说说类的初始化:

在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。一个类变量初始化语句是

变量声明后的等号和表达式:
Java代码 复制代码

    class Example {  
           static int size = 3 * (int) (Math.random() * 5.0);  
    } 



静态初始化语句是一个以static开头的语句块:
Java代码 复制代码

    class Example{  
         static int size;  
         static {  
               size = 3 * (int) (Math.random() * 5.0);  
         }  
    } 

所有的类变量初始化语句和类型的静态初始化语句都被Java编译器收集到了一起,放在一个特殊的方法中。这个方法就是<clinit>



我们在来看看<init>这个方法:

<init>方法是在一个类进行对象实例化时调用的。实例化一个类有四种途径:调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。



Java编译器会为它的每一个类都至少生成一个实例初始化方法。在Class文件中,被称为"<init>"



现在知道了吧, 一个是用于初始化静态的类变量, 一个是初始化实例变量!

猜你喜欢

转载自j-yy2008.iteye.com/blog/1775443