My開発メモ

動的Webアプリの場合は Class.forName()は必要

ある時、なんとなく Class.forName()を記述せずに
データベースに接続する処理(DriverManager.getConnection(URL, USER, PADD)) を
実行したら、できた。

これは、Javaアプリだったので、Tomcat9(Java11) をターゲットにしたアプリで
やったら、これはだめだった。

Javaアプリの場合は Class.forName()がなくとも DBドライバーはロードされるのに、
動的Webアプリの場合は Class.forName()が必要なのだが、それはなぜか?

準備

準備として、DAOファイルに以下のメソッドを仕込んでおく。

public void showDriverList() {
  Enumeration<Driver> drivers = DriverManager.getDrivers();
  if (drivers.hasMoreElements()) {
    while (drivers.hasMoreElements()) {
      Driver d = drivers.nextElement();
      System.out.print(d.getClass().getName());
      System.out.print(" ");
      System.out.println(d.getClass().getClassLoader());
    }
  } else {
    System.out.println("ドライバーはありません。");
  }    
}

これを Class.forName()のあとで動作させる。

try {
  Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
  throw new IllegalStateException("適切なDBドライバーが見つかりません");
}
showDriverList();

結果

動的Webアプリケーション(Tomcat)の場合は、以下のように表示された。

org.h2.Driver ParallelWebappClassLoader
  context: twoTablesSample
  delegate: false
----------> Parent Classloader:
java.net.URLClassLoader@4f3f5b24

Javaアプリケーションの場合は、以下のように表示された。

org.h2.Driver jdk.internal.loader.ClassLoaders$AppClassLoader@55054057

org.h2.Driverをロードするクラスローダーが違っていた。

そして、アプリケーション・クラスローダーの場合は、Class.forName()がなくても、
org.h2.Driver は自動的にロードされるみたい。

もちろん、h2-2.2.224.jar のビルドパスへの追加は必要である。

カテゴリー: Java, memo

タグ: Class.forName, DriverManager, ドライバー

カウント: 133