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

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

编辑:它不是NoResultException,NoResultException是Exception的消息。 stackTrace在下面

如果我将导入删除到javax.persistence.NoResultException并只捕获一个通用的Exception e ,则代码可以正常工作。

我的问题是:

  1. 为什么未调用的方法中的代码会影响构造函数? (也没有在构造函数中调用)
  2. 为什么ClassLoader抛出一个不应抛出的exception? 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 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 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以及它失败的时刻的分步图像:

调用新的ClassB时STEP INTO让我得到loadClassInternal(String) 调用新的ClassB时STEP INTO让我得到loadClassInternal(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让我得到loadClass(String ) STEP RETURN让我得到loadClass(String)

STEP OVER让我得到loadClassInternal(String) STEP OVER让我得到loadClassInternal(String)

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

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

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