类构造函数无法在类加载上抛出异常

时间:2012-07-31 10:47:57

标签: java

我有一个构造函数在第一次调用new时失败,因为类javax.persistence.NoResultException的异常是在一个Class'方法中捕获的。

编辑:这不是NoResultException,NoResultException是Exception的消息。 stackTrace低于

如果我将导入移至javax.persistence.NoResultException并仅捕获通用Exception e,则代码可以正常运行。

我的问题是:

  1. 为什么未调用的方法中的代码会影响构造函数? (也没有在构造函数中调用)
  2. 为什么ClassLoader会抛出一个不应该抛出的异常?根据JavaDoc,ClassLoader.loadClass()抛出ClassNotFoundException
  3. 抓住javax.persistence.NoResultException以及导入是旧代码,它们设法在版本之间存活,我将其删除并修复了,但是我现在想了解这背后的原因。

    STACKTRACE:

    java.lang.NoClassDefFoundError: javax/persistence/NoResultException
        at xxx.xxxxxx.xxxxxxx.xxxx.xxxx.xxxxxxxxxxxx.xxxxxxxxxxxxxxx(ClassB.java)
        ...
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)
    Caused by: java.lang.ClassNotFoundException: javax.persistence.NoResultException
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
        ... 10 more
    

    转到最后查看调试程序的逐步图像及其失败的时刻

    失败代码:

    // ClassB.java
    
    import javax.persistence.NoResultException; // NOTICE THE IMPORT
    
    public ClassB{
        private UserInfo user;
        private WebServiceBDelegate port;
        private Connection conn;
    
        public ClassB (UserInfo user, Connection conn) throws Exception {
            System.out.println("CLASS B CONSTRUCTOR");
            this.user = user;
            this.conn = conn;
            this.port = new WebServiceBService().getForwardingPort();
        }
    
        public boolean methodB(List<String> list){
            try{
                // Check some stuff on database using this.conn
            } catch(NoResultException nre){         // NOTICE THE CATCH
                String something = getSomething();
            }
            // Get the values to invoke SOAP service using this.conn
            status = port.operationB(values);
            if(status > 0)
                return true;
            return false;
        }
    }
    

    工作代码:

    // ClassB.java
    
    public ClassB{
        private UserInfo user;
        private WebServiceBDelegate port;
        private Connection conn;
    
        public ClassB (UserInfo user, Connection conn) throws Exception {
            System.out.println("CLASS B CONSTRUCTOR");
            this.user = user;
            this.conn = conn;
            this.port = new WebServiceBService().getForwardingPort();
        }
    
        public boolean methodB(List<String> list){
            try{
                // Check some stuff on database using this.conn
            } catch(Exception e){         // THIS IS THE CHANGED CATCH
                String something = getSomething();
            }
            // Get the values to invoke SOAP service using this.conn
            status = port.operationB(values);
            if(status > 0)
                return true;
            return false;
        }
    }
    

    以下是进入INTO类构造函数时调试器的逐步映像,以及JVM默认的ClassLoader及其失败的时刻:

    STEP INTO when calling new ClassB gets me to loadClassInternal(String) STEP INTO when calling new ClassB gets me to loadClassInternal(String)

    STEP INTO loadClassInternal(String), gets me to loadClass(String,boolean) STEP INTO loadClassInternal(String), gets me to loadClass(String,boolean)

    STEP INTO loadClass(String,boolean), as far as I can get, now STEP RETURN STEP INTO loadClass(String,boolean), as far as I can get, now STEP RETURN

    STEP RETURN gets me to loadClass(StringSTEP RETURN gets me to loadClass(String)

    STEP OVER gets me to loadClassInternal(String) STEP OVER gets me to loadClassInternal(String)

    STEP OVER gives me javax.persistence.NoResultException STEP OVER gives me javax.persistence.NoResultException

    在我的代码中最终回到最后并结束执行

1 个答案:

答案 0 :(得分:2)

  1. 首次访问时,类将加载到ClassLoader中。代码中的第一个“new”语句将类加载到ClassLoader中,ClassLoader随后会检查它是否实际上可以访问类的所有依赖项(即NoResultException)。
  2. 你没有明确说明ClassLoader抛出了什么,但我的猜测是它会抛出一个ClassNotFoundException,详细说明NoResultException不在你的类路径上,因此无法加载。这也是为什么当你删除有问题的导入和捕获时它的工作原理。