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.банки в cliTest.jar (my JAR) полученная банка жирная (550kB и включает классы в этой банке тоже). Или я могу исключить это. В любом случае, бегом!--5-->

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.run(Unknown Source)
        at java.net.URLClassLoader.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 в каталог, содержащий банку, но по-прежнему без изменений.

позже редактировать 2 : на основе ответа Николая я сделал следующее:

  1. удалить существующий артефакт
  2. создал новый артефакт так:

enter image description here

enter image description here

.. и вот результат:

enter image description here

  1. построение -> построить артефакты -> cliTest.сосуд>- Перестроить

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

[cliTest.jar 566 KB был сгенерирован]

java-jar cliTest.Джар

теперь я понимаю :

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.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.access0(Unknown Source)
    at java.net.URLClassLoader.run(Unknown Source)
    at java.net.URLClassLoader.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)

3 ответов


использовать java -cp вместо java -jar и поместите все ваши зависимости jars в classpath.

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

EDIT:

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

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

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

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

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


Ну я бы построил банке без sqljdbc4.фляги врезал.

второе, что я должен был выполнить команду так:

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

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


Ну, если вы используете 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>