java.lang.NoClassDefFoundError:如何解决–第3部分

本文是我们的NoClassDefFoundError故障排除系列的第3部分。 正如我在第一篇文章中提到的那样,有许多可能导致NoClassDefFoundError的问题。 本文将重点介绍该问题的最常见原因之一:Java类静态初始化程序块或变量的失败。

将提供一个示例Java程序,我鼓励您从工作站上编译并运行此示例,以正确复制和理解此类NoClassDefFoundError问题。

再谈Java静态初始值设定项

Java编程语言为您提供了“静态”初始化变量或代码块的功能。 这可以通过“静态”变量标识符或在Java类的标头使用static {}块来实现。 静态初始化程序保证在JVM生命周期中只能执行一次 ,并且通过设计是线程安全的,这使其在静态数据初始化(例如内部对象缓存,记录器等)中的使用非常吸引人。

问题是什么? 我将再次重复,保证静态初始化程序在JVM生命周期中只能执行一次……这意味着此类代码在Class加载时执行,并且在您重新启动JVM之前不会再次执行。 现在,如果当时执行的代码(@Class加载时间)以未处理的异常终止会发生什么?

欢迎来到java.lang.NoClassDefFoundError问题案例#2!

NoClassDefFoundError问题案例2 –静态初始化失败

静态初始化程序代码失败,再加上尝试创建受影响的(未加载)类的新实例的连续尝试,便会发生此类问题。

示例Java程序

以下简单的Java程序按以下方式拆分:

–主Java程序NoClassDefFoundErrorSimulator
–受影响的Java类ClassA
– ClassA为您提供一个ON / OFF开关,使您可以复制要研究的问题类型

该程序只是试图尝试创建ClassA的新实例3次(一个接一个)。 它将演示静态变量或静态块初始化程序的初始失败,再加上尝试创建受影响的类的新实例的连续尝试,将触发java.lang.NoClassDefFoundError。

#### NoClassDefFoundErrorSimulator.java
package org.ph.javaee.tools.jdk7.training2;

/**
 * NoClassDefFoundErrorSimulator
 * @author Pierre-Hugues Charbonneau
 *
 */
public class NoClassDefFoundErrorSimulator {
       
        /**
         * @param args
         */
        public static void main(String[] args) {
               System.out.println("java.lang.NoClassDefFoundError Simulator - Training 2");
               System.out.println("Author: Pierre-Hugues Charbonneau");
               System.out.println("http://javaeesupportpatterns.blogspot.com\n\n");              
                             
               try {                 
                       // Create a new instance of ClassA (attempt #1)
                       System.out.println("FIRST attempt to create a new instance of ClassA...\n");        
                       ClassA classA = new ClassA();
                      
               } catch (Throwable any) {
                       any.printStackTrace();
               }             
              
               try {                 
                       // Create a new instance of ClassA (attempt #2)
                       System.out.println("\nSECOND attempt to create a new instance of ClassA...\n");        
                       ClassA classA = new ClassA();
                      
               } catch (Throwable any) {                   
                       any.printStackTrace();
               }      
              
               try {                 
                       // Create a new instance of ClassA (attempt #3)
                       System.out.println("\nTHIRD attempt to create a new instance of ClassA...\n");        
                       ClassA classA = new ClassA();
                      
               } catch (Throwable any) {                   
                       any.printStackTrace();
               }             
              
               System.out.println("\n\ndone!");
        }
}
#### ClassA.java
package org.ph.javaee.tools.jdk7.training2;

/**
 * ClassA
 * @author Pierre-Hugues Charbonneau
 *
 */
public class ClassA {
       
        private final static String CLAZZ = ClassA.class.getName();
        // Problem replication switch ON/OFF
        private final static boolean REPLICATE_PROBLEM1 = true; // static variable initializer
        private final static boolean REPLICATE_PROBLEM2 = false; // static block{} initializer
       
        // Static variable executed at Class loading time
        private static String staticVariable = initStaticVariable();
       
        // Static initializer block executed at Class loading time
        static {
              
               // Static block code execution...
               if (REPLICATE_PROBLEM2) throw new IllegalStateException("ClassA.static{}: Internal Error!");
        }
       
        public ClassA() {
               System.out.println("Creating a new instance of "+ClassA.class.getName()+"...");
        }
       
        /**
         *
         * @return
         */
        private static String initStaticVariable() {
              
               String stringData = "";
              
               if (REPLICATE_PROBLEM1) throw new IllegalStateException("ClassA.initStaticVariable(): Internal Error!");
              
               return stringData;
        }
}

问题重现

为了复制问题,我们将简单地“自愿”触发静态初始化器代码的失败。 请简单地启用您要研究的问题类型,例如静态变量或静态块初始化程序失败:

// Problem replication switch ON (true) / OFF (false)
        private final static boolean REPLICATE_PROBLEM1 = true; // static variable initializer
        private final static boolean REPLICATE_PROBLEM2 = false; // static block{} initializer

现在,让我们在两个开关都处于OFF的情况下运行程序(两个布尔值都为false)
##基准(正常执行)

java.lang.NoClassDefFoundError Simulator - Training 2
             
            
            
             Author: Pierre-Hugues Charbonneau
             
            
            
             http://javaeesupportpatterns.blogspot.com
             
            
            
          
FIRST attempt to create a new instance of ClassA...
             
            
            
           
Creating a new instance of org.ph.javaee.tools.jdk7.training2.ClassA...
             
            
            
SECOND attempt to create a new instance of ClassA...
             
            
            
Creating a new instance of org.ph.javaee.tools.jdk7.training2.ClassA...
             
            
            
THIRD attempt to create a new instance of ClassA...
             
            
            
Creating a new instance of org.ph.javaee.tools.jdk7.training2.ClassA...
             
            
            
done!

对于初始运行(基准),主程序能够成功创建3个ClassA实例,而不会出现问题。

##问题再现运行(静态变量初始化程序失败)

java.lang.NoClassDefFoundError Simulator - Training 2
             
            
            
             Author: Pierre-Hugues Charbonneau
             
            
            
             http://javaeesupportpatterns.blogspot.com
             
            
            
FIRST attempt to create a new instance of ClassA...
             
            
            
java.lang.ExceptionInInitializerError
             
            
            
                     at org.ph.javaee.tools.jdk7.training2.NoClassDefFoundErrorSimulator.main(
             NoClassDefFoundErrorSimulator.java:21
             )
             
            
            
             Caused by: 
             java.lang.IllegalStateException
             : ClassA.initStaticVariable(): Internal Error!
             
            
            
                     at org.ph.javaee.tools.jdk7.training2.ClassA.initStaticVariable(
             ClassA.java:37
             )
             
            
            
                     at org.ph.javaee.tools.jdk7.training2.ClassA.<clinit>(
            ClassA.java:16
             )
             
            
            
                     ... 1 more
             
            
            
SECOND attempt to create a new instance of ClassA...
             
            
            
java.lang.NoClassDefFoundError: Could not initialize class org.ph.javaee.tools.jdk7.training2.ClassA
             
            
            
                     at org.ph.javaee.tools.jdk7.training2.NoClassDefFoundErrorSimulator.main(
           NoClassDefFoundErrorSimulator.java:30
             )
             
            
            
THIRD attempt to create a new instance of ClassA...
             
            
            
java.lang.NoClassDefFoundError: Could not initialize class org.ph.javaee.tools.jdk7.training2.ClassA
             
            
            
                     at org.ph.javaee.tools.jdk7.training2.NoClassDefFoundErrorSimulator.main(
           NoClassDefFoundErrorSimulator.java:39>
             )
             
            
            
done!

##问题再现运行(静态块初始化程序失败)

java.lang.NoClassDefFoundError Simulator - Training 2
             
            
            
             Author: Pierre-Hugues Charbonneau
             
            
            
             http://javaeesupportpatterns.blogspot.com
             
            
            
             
FIRST attempt to create a new instance of ClassA...
             
            
            
java.lang.ExceptionInInitializerError
             
            
            
                    at org.ph.javaee.tools.jdk7.training2.NoClassDefFoundErrorSimulator.main(
             NoClassDefFoundErrorSimulator.java:21
             )
             
            
            
             Caused by: 
             java.lang.IllegalStateException>
             : ClassA.static{}: Internal Error!
             
            
            
                    at org.ph.javaee.tools.jdk7.training2.ClassA.<clinit>(
             ClassA.java:22
             )
             
            
            
                    ... 1 more
             
            
            
SECOND attempt to create a new instance of ClassA...
             
            
            
java.lang.NoClassDefFoundError: Could not initialize class org.ph.javaee.tools.jdk7.training2.ClassA
             
            
            
                    at org.ph.javaee.tools.jdk7.training2.NoClassDefFoundErrorSimulator.main(
             NoClassDefFoundErrorSimulator.java:30
             )
             
            
            
THIRD attempt to create a new instance of ClassA...
             
            
            
java.lang.NoClassDefFoundError: Could not initialize class org.ph.javaee.tools.jdk7.training2.ClassA
             
            
            
                    at org.ph.javaee.tools.jdk7.training2.NoClassDefFoundErrorSimulator.main(
             NoClassDefFoundErrorSimulator.java:39
             )
             
            
            
done!

发生了什么? 如您所见,第一次尝试创建ClassA的新实例确实触发了java.lang.ExceptionInInitializerError。 此异常表示我们的静态变量&bloc的静态初始化程序失败,这正是我们想要实现的目标。

此时要了解的关键点是,此故障确实阻止了ClassA的整个类加载。 如您所见,尝试#2和尝试#3都生成了java.lang.NoClassDefFoundError,为什么? 好吧,因为第一次尝试失败了,所以可以防止ClassA的类加载。 连续尝试在当前ClassLoader中创建ClassA的新实例的做法一遍又一遍地产生了java.lang.NoClassDefFoundError,因为在当前ClassLoader中未找到ClassA。

如您所见,在此问题上下文中,NoClassDefFoundError只是另一个问题的症状后果 。 最初的问题是在静态初始化程序代码失败后触发的ExceptionInInitializerError。 这清楚地说明了使用Java静态初始化程序时正确进行错误处理和记录的重要性。

建议和解决策略

现在在下面找到我对NoClassDefFoundError问题案例2的建议和解决策略:
–检查java.lang.NoClassDefFoundError错误并确定缺少的Java类
–对受影响的类执行代码演练,并确定其是否包含静态初始化程序代码(变量和静态块) –检查您的服务器和应用程序日志,确定是否有任何错误(例如ExceptionInInitializerError)源自静态初始化程序代码–确认后,进一步分析代码并确定初始化程序代码失败的根本原因。 您可能需要添加一些额外的日志记录以及适当的错误处理,以防止并更好地处理将来的静态初始化程序代码失败

请随时发表任何问题或评论。

第4部分将开始介绍与类加载器问题有关的NoClassDefFoundError问题。

参考: java.lang.NoClassDefFoundError:如何解决–第3部分,来自我们的JCG合作伙伴 Pierre-Hugues Charbonneau,位于Java EE支持模式和Java教程博客。


翻译自: https://www.javacodegeeks.com/2012/07/javalangnoclassdeffounderror-how-to.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值