0

newクラスの例外がjavax.persistence.NoResultExceptionクラスのメソッドの1つでキャッチされているため、への最初の呼び出しで失敗するコンストラクターがあります。

編集:それはNoResultExceptionではなく、NoResultExceptionは例外のメッセージでした。stackTraceは以下のとおりです

インポートを削除しjavax.persistence.NoResultExceptionてジェネリックだけをキャッチすると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まで、および失敗した瞬間のステップバイステップのイメージです。

新しいClassBを呼び出すときにSTEPINTOを実行すると、loadClassInternal(String)が表示されます。 新しいClassBを呼び出すときにSTEPINTOを実行すると、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)に移動します

STEPOVERでjavax.persistence.NoResultExceptionが発生します STEPOVERでjavax.persistence.NoResultExceptionが発生します

ステップオーバーすると、コードが最後に戻り、実行が終了します

4

1 に答える 1

2
  1. クラスは、最初のアクセス時にClassLoaderにロードされます。コードの最初の「new」ステートメントは、クラスをClassLoaderにロードします。その後、ClassLoaderは、クラスのすべての依存関係(つまり、NoResultException)に実際にアクセスできるかどうかをチェックします。
  2. ClassLoaderによって何がスローされているかを明確にしていませんが、私の推測では、NoResultExceptionがクラスパスにないことを詳細に示すClassNotFoundExceptionがスローされるため、ロードできません。これが、問題のあるインポートとキャッチを削除したときに機能する理由でもあります。
于 2012-07-31T10:59:45.070 に答える