0

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

编辑:它不是 NoResultException,NoResultException 是异常的消息。堆栈跟踪如下

如果我删除 import tojavax.persistence.NoResultException并只捕获一个 generic Exception e,代码就可以工作。

我的问题是:

  1. 为什么尚未调用的方法中的代码会影响构造函数?(也没有在构造函数中调用)
  2. 为什么 ClassLoader 会抛出一个不应该抛出的异常?ClassLoader.loadClass()ClassNotFoundException根据 JavaDoc抛出。

javax.persistence.NoResultException 的捕获以及导入是在版本之间设法生存的旧代码,我将其删除并且已修复,但是我现在想知道这背后的原因。

堆栈跟踪:

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 调用 new ClassB 时让我加载ClassInternal(String) STEP INTO 调用 new ClassB 时让我加载ClassInternal(String)

STEP INTO loadClassInternal(String),让我去 loadClass(String,boolean) STEP INTO loadClassInternal(String),让我去 loadClass(String,boolean)

STEP INTO loadClass(String,boolean),据我所知,现在 STEP RETURN STEP INTO loadClass(String,boolean),据我所知,现在 STEP RETURN

STEP RETURN 让我加载类(字符串STEP RETURN 让我加载类(字符串)

STEP OVER 让我加载ClassInternal(String) STEP OVER 让我加载ClassInternal(String)

STEP OVER 给我 javax.persistence.NoResultException STEP OVER 给我 javax.persistence.NoResultException

STEP OVER 让我回到我的代码的最后并结束执行

4

1 回答 1

2
  1. 该类在首次访问时被加载到 ClassLoader 中。代码中的第一个“new”语句将类加载到 ClassLoader 中,后者随后检查它是否实际上可以访问类的所有依赖项(即 NoResultException)。
  2. 你没有说清楚 ClassLoader 抛出了什么,但我猜它确实抛出了一个 ClassNotFoundException ,详细说明 NoResultException 不在你的类路径上,所以它不能被加载。这也是当您删除有问题的导入和捕获时它起作用的原因。
于 2012-07-31T10:59:45.070 回答