私は 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();
}
}
SQL Server が利用可能な状態で IDE (IntelliJ IDEA 12.1.6 Community Edition) でアプリを実行すると、アプリは期待どおりに正常に動作します。
SQL Server ドライバーは Microsoft からダウンロードされ、外部ライブラリとして追加されます。JAR ファイルとしてアーティファクトを作成しました:
さて、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: Nikolay の回答に基づいて、次の操作を実行しました。
- 既存のアーティファクトを削除しました
- 次のように新しいアーティファクトを作成しました:
..そして結果は次のようになりました:
ビルド -> ビルド成果物 -> cliTest.jar -> 再構築
次の内容を含むフォルダーでの 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)
ベストアンサー1
java -cp
の代わりにを使用しjava -jar
、依存関係の jar をすべてクラスパスに配置します。
もう 1 つの方法は、すべての依存関係を 1 つの jar にパックし、 を使用してアプリケーションを実行できるようにすることですjava -jar
。
編集:
Java では、*.jar ファイルには大量のクラスが含まれます。独自のアプリを構築する場合、通常、結果の jar ファイルには独自のクラスのみが含まれますが、使用する外部ライブラリからクラスをロードする必要があります (いわゆる依存関係)。
これには 2 つの方法があります。
アプリケーション用のフォルダーを作成し、たとえば、
lib
アプリケーションjarとすべての依存関係を配置します。次に、を使用してアプリケーションを実行するjava -cp lib:/\* com.company.Main
か(@NilsHさん、このバリエーションが懐かしいです)、ファイルを作成し、説明されているように内部の属性をMANIFEST.MF
指定します。Main-Class
Classpath
ここ特別なツール (ビルドに maven を使用する場合は maven-dependency-plugin など) を使用して、独自のクラスでも外部のクラスでも、すべてのクラスを単一の jar にパックします。 1 つの巨大なファイルを取得し、 を使用して実行できます
java -jar cliTest.jar
。
一般的に、最初のアプローチが好まれ、MANIFEST.MF
ファイルを使用するのが適切な形式です。