【问题标题】:Class Constructor fails throwing Exception on Class Loading类构造函数在类加​​载时抛出异常失败
【发布时间】:2012-07-31 10:47:57
【问题描述】:

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

编辑:这不是 NoResultException,NoResultException 是异常的消息。 stackTrace 在下面

如果我删除对javax.persistence.NoResultException 的导入并仅捕获通用Exception e,则代码有效。

我的问题是:

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

对于 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 when calling new ClassB gets me to loadClassInternal(String)

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 RETURN gets me to loadClass(String)

STEP OVER gets me to loadClassInternal(String)

STEP OVER gives me javax.persistence.NoResultException

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

【问题讨论】:

标签: java


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

【讨论】:

  • 我认为你成功了,which subsequently checks whether it actually has access to all the dependencies of your class,我认为它只会在需要时检查依赖关系。让我检查一下抛出的异常是什么,我只是假设它是图片六中的javax.persistence.NoResultException
  • 谢谢!就是这样!我必须捕获一个 Throwable 才能检查异常,我花了一段时间才意识到这一点。它没有用异常捕获它。我更新了我的问题以显示 StackTrace
猜你喜欢
  • 2014-11-03
  • 2017-02-09
  • 1970-01-01
  • 2017-08-28
  • 2011-10-10
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2021-09-18
相关资源
最近更新 更多