web-dev-qa-db-ja.com

JARの実行時にClassNotFoundException、IntelliJで実行中にエラーが発生しないIDEA

私はちょうどJavaアプリ(私は.NETの経験があります)をビルドし始めています。コード全体がこれである小さなテストアプリをビルドしようとしていました:

package com.company;

import com.Microsoft.sqlserver.jdbc.SQLServerDataSource;

import Java.sql.Connection;
import Java.sql.PreparedStatement;
import Java.sql.ResultSet;
import Java.sql.SQLException;

public class Main {

    public static void main(String[] args) throws SQLException {
        System.out.println("Buna lume!");

        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setIntegratedSecurity(true);
        ds.setServerName("localhost");
        ds.setPortNumber(1433);
        ds.setDatabaseName("Test");
        Connection con = ds.getConnection();

        String SQL = "SELECT * FROM Test WHERE ID = ?";
        PreparedStatement stmt = con.prepareStatement(SQL);
        stmt.setInt(1, 2);
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            System.out.println(rs.getInt(1) + ", " + rs.getString(2));
        }
        rs.close();
        stmt.close();

        con.close();
    }
}

IDE(IntelliJ IDEA 12.1.6 Community Edition))でアプリを実行すると、SQL Serverが利用可能になり、アプリはそれとまったく同じようにうまく実行されますすべきです。

SQL ServerドライバーはMicrosoftからダウンロードされ、外部ライブラリとして追加されます。アーティファクトをJARファイルとして作成しました。

enter image description here

ここで、sqljdbc4.jarをcliTest.jar(私のJAR)に含めた場合、結果のJARは太くなります(550kBで、そのJARにもクラスが含まれます)。または除外できます。どちらにしても、実行中

Java -jar cliTest.jar

結果

Buna lume!
Exception in thread "main" Java.lang.NoClassDefFoundError: com/Microsoft/sqlserv
er/jdbc/SQLServerDataSource
        at com.company.Main.main(Main.Java:15)
Caused by: Java.lang.ClassNotFoundException: com.Microsoft.sqlserver.jdbc.SQLSer
verDataSource
        at Java.net.URLClassLoader$1.run(Unknown Source)
        at Java.net.URLClassLoader$1.run(Unknown Source)
        at Java.security.AccessController.doPrivileged(Native Method)
        at Java.net.URLClassLoader.findClass(Unknown Source)
        at Java.lang.ClassLoader.loadClass(Unknown Source)
        at Sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at Java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

私はかなり基本的なものを見逃しているに違いないが、これが正確に何を引き起こしているのか正確には理解できない。

LE1:JARを含むディレクトリにsqljdbc4.jar(必須ではないようですが)とsqljdbc_auth.dllを追加しようとしましたが、変更はありませんでした。

後の編集2:ニコライの回答に基づいて、次のことを行いました。

  1. 既存のアーティファクトを削除しました
  2. そのような新しいアーティファクトを作成しました:

enter image description here

enter image description here

..そしてこれをもたらした:

enter image description here

  1. ビルド->アーティファクトのビルド-> cliTest.jar->再ビルド

  2. 次を含むフォルダでのCMDプロンプト:

[cliTest.jar 566 KBが生成されました]

Java -jar cliTest.jar

今私は得る:

Exception in thread "main" Java.lang.SecurityException: Invalid signature file d
igest for Manifest main attributes
    at Sun.security.util.SignatureFileVerifier.processImpl(Unknown Source)
    at Sun.security.util.SignatureFileVerifier.process(Unknown Source)
    at Java.util.jar.JarVerifier.processEntry(Unknown Source)
    at Java.util.jar.JarVerifier.update(Unknown Source)
    at Java.util.jar.JarFile.initializeVerifier(Unknown Source)
    at Java.util.jar.JarFile.getInputStream(Unknown Source)
    at Sun.misc.URLClassPath$JarLoader$2.getInputStream(Unknown Source)
    at Sun.misc.Resource.cachedInputStream(Unknown Source)
    at Sun.misc.Resource.getByteBuffer(Unknown Source)
    at Java.net.URLClassLoader.defineClass(Unknown Source)
    at Java.net.URLClassLoader.access$100(Unknown Source)
    at Java.net.URLClassLoader$1.run(Unknown Source)
    at Java.net.URLClassLoader$1.run(Unknown Source)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(Unknown Source)
    at Java.lang.ClassLoader.loadClass(Unknown Source)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at Java.lang.ClassLoader.loadClass(Unknown Source)
    at Sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
16
Andrei Rînea

まあ私はsqljdbc4.jarが埋め込まれていないJARをビルドしたはずです。

次のようにコマンドを実行する必要があります:

Java -classpath sqljdbc4.jar;cliTest.jar com.company.Main

..そして、すべてがうまくいきました!

4
Andrei Rînea

Java -cpの代わりにJava -jarを使用し、すべての依存関係jarをクラスパスに配置します。

もう1つの方法は、すべての依存関係を単一のjarにパックして、Java -jarを使用してアプリケーションを実行できるようにすることです。

編集:

Java * .jarファイルには大量のクラスが含まれます。通常、独自のアプリをビルドすると、結果のjarファイルにはクラスのみが含まれますが、使用する外部ライブラリからクラスをロードする必要があります(いわゆる依存関係)。

次の2つの方法で行うことができます。

  1. たとえば、libというアプリケーション用のフォルダーを作成し、アプリケーションjarとすべての依存関係を配置します。次に、Java -cp lib:/\* com.company.Mainを使用してアプリケーションを実行するか、(@ NilsHのおかげで、このバリアントがありません)MANIFEST.MFファイルを作成し、説明に従ってMain-ClassおよびClasspath属性を指定します ここ

  2. 特別なツール(ビルドにmavenを使用する場合はmaven-dependency-pluginのような)を使用して、すべてのクラス、独自のクラス、単一のjarの外部のクラスをパックします。 1つの巨大なファイルを取得し、Java -jar cliTest.jarを使用して実行できます。

一般に、最初のアプローチが推奨され、MANIFEST.MFファイルを使用するのが適切な形式です。

5
Nikolay