运行JAR时ClassNotFoundException,在IntelliJ IDEA中运行时没有错误

时间:2013-11-03 19:55:50

标签: java jar intellij-idea classnotfoundexception sqljdbc

我刚开始构建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社区版)中运行该应用程序,让SQL Server可用,该应用程序可以正常运行。

SQL Server驱动程序从Microsoft下载并添加为外部库。我创建了一个工件作为JAR文件:

enter image description here

现在,如果我在cliTest.jar(我的JAR)中包含sqljdbc4.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的回答,我做了以下几点:

  1. 删除现有工件
  2. 像这样创建了一个新工件:
  3. enter image description here

    enter image description here

    ..并且结果如此:

    enter image description here

    1. 构建 - >构建工件 - > cliTest.jar - >重建

    2. CMD提示包含以下内容的文件夹:

    3. [生成了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)
      

4 个答案:

答案 0 :(得分:4)

使用java -cp代替java -jar,并将所有依赖项jar放入类路径。

另一种方法是将所有依赖项打包到单个jar,允许您使用java -jar运行应用程序。

修改

在Java * .jar文件中包含大量类。当您构建自己的应用程序时,通常,结果jar文件只包含您的类,但仍然必须从您使用的外部库(所谓的依赖项)加载类。

可以通过两种不同的方式完成:

  1. 您可以为应用程序创建一个文件夹,例如,名为lib,并将您的应用程序jar和所有依赖项放入其中。然后使用java -cp lib:/\* com.company.Main运行应用程序或(感谢@NilsH,我想念此变体)您创建MANIFEST.MF文件并在内部指定Main-ClassClasspath属性{{3} }

  2. 您使用特殊工具(如maven-dependency-plugin,如果您使用maven进行构建)来打包所有类,无论是您自己的类,还是单个jar的外部类。您有一个巨大的文件,可以使用java -jar cliTest.jar运行它。

  3. 通常,首选方法是首选,使用MANIFEST.MF文件是一种很好的形式。

答案 1 :(得分:3)

我应该在没有嵌入sqljdbc4.jar的情况下构建JAR。

我应该第二件事就是这样运行命令:

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

..然后一切顺利!

答案 2 :(得分:0)

我对 build.gradle 进行了以下更改,其中 <packageName>package <packageName>

这会出现在您文件的顶部 Main.ktMain.java

  manifest {
-    attributes "Main-Class": "MainKt"
+    attributes "Main-Class": "<packageName>.MainKt"
  }
  from {
    configurations.runtimeClasspath.collect {
      f -> f.isDirectory() ? f : zipTree(f)
    }
  }
  archiveName "pipeline-server.jar"
}

答案 3 :(得分:-1)

如果您正在使用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>