ClassNotFoundException при запуске JAR, никаких ошибок во время работы в 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 будет толстым (550 КБ и включает классы в этом 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: Я попытался добавить sqljdbc4.jar(хотя это и не казалось необходимым) и sqljdbc_auth.dll в каталоге, содержащем JAR, но все равно никаких изменений.

Далее отредактируйте 2: На основании ответа Николая я сделал следующее:

  • Удален существующий артефакт
  • Создал новый артефакт:

enter image description here

enter image description here

.. и привело к следующему:

enter image description here

  1. Построить → Построить артефакты → cliTest.jar → Восстановить

  2. CMD Запрос в папке, содержащей:

[cliTest.jar создано 566 КБ]

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

Ну, я должен был создать JAR без встроенного sqljdbc4.jar.

Во-вторых, я должен запустить команду следующим образом:

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

.. а потом все сработало!

Ответ 2

Используйте java -cp вместо java -jar и поместите все ваши javascript-зависимости в путь к классам.

Другим способом является пакет всех зависимостей для одиночной банки, позволяющий запускать приложение с помощью java -jar.

EDIT:

В файле Java *.jar содержится основная часть классов. Когда вы создаете собственное приложение, как правило, файл jar result содержит только ваши классы, но все равно приходится загружать классы из используемых вами внешних библиотек (так называемые зависимости).

Это можно сделать двумя разными способами:

  • Вы создаете папку для своего приложения, например, называемую lib, и помещаете в нее приложение jar и все зависимости. Затем вы запускаете приложение с помощью java -cp lib:/\* com.company.Main или (спасибо @NilsH, я пропустил этот вариант), вы делаете файл MANIFEST.MF и указываете Main-Class и Classpath атрибуты внутри, как описано здесь

  • Вы используете специальный инструмент (например, maven-dependency-plugin, если вы используете maven для сборки) для упаковки всех классов, либо ваших, либо внешних, либо одиночных. У вас есть один огромный файл и его можно запустить с помощью java -jar cliTest.jar.

Как правило, первый подход является предпочтительным, и использование файла MANIFEST.MF является хорошей формой.

Ответ 3

Хорошо, если вы используете maven, вы можете использовать maven-shade-plugin для включения зависимого jar в исполняемый jar фрагмент pom.xml приведен ниже.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">                                      <mainClass>com.main.class.YouMainClass</mainClass>
                                </transformer>
                            </transformers>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                    </execution>
                </executions>
            </plugin>