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

时间:2023-01-08 00:55:51

I'm just starting to build Java apps (I do have .NET experience) and I was trying to build a small test app whose whole code is this :

我刚刚开始开发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();
    }
}

If I run the app in the IDE (IntelliJ IDEA 12.1.6 Community Edition), having the SQL Server available, the app runs fine doing exactly what it should.

如果我在IDE中运行这个应用程序(IntelliJ IDEA 12.1.6 Community Edition),有了SQL Server,应用程序就可以正常运行了。

The SQL Server Driver is downloaded from Microsoft and added as an External Library. I have created an artifact as JAR file :

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

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

Now, if I include the sqljdbc4.jar in the cliTest.jar (my JAR) the resulted JAR is fat (550kB and includes the classes in that JAR too). Or I can exclude it. Either way, running

现在,如果我包含sqljdbc4。jar的阴蒂。jar(我的jar)结果的jar是fat (550kB,也包含那个jar中的类)。或者我可以排除它。无论哪种方式,运行

java -jar cliTest.jar

Results in

结果

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

I bet I'm missing something quite basic but I just can't figure out what exactly is causing this.

我打赌我错过了一些非常基本的东西,但我就是搞不清到底是什么导致了这一切。

LE1 : I tried adding sqljdbc4.jar (although it didn't seem necessary) and sqljdbc_auth.dll in the directory containing the JAR but still no change.

LE1:我尝试添加sqljdbc4。jar(尽管看起来没有必要)和sqljdbc_auth。包含JAR的目录中的dll,但仍然没有更改。

Later edit 2 : Based on Nikolay's answer I've done the following :

后来的编辑2:根据尼古拉的回答,我做了如下工作:

  1. Deleted the existing artifact
  2. 删除现有的工件
  3. Created a new artifact like so :
  4. 创建了一个新的工件,比如:

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

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

.. and resulted this :

. .和结果:

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

  1. Build -> Build artifacts -> cliTest.jar -> Rebuild

    构建->构建构件-> cliTest。jar - >重建

  2. CMD Prompt at the folder containing :

    CMD提示符位于包含:

[cliTest.jar 566 KB was generated]

(阴核。生成jar 566 KB]

java -jar cliTest.jar

java jar cliTest.jar

Now I get :

现在我得到:

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)

3 个解决方案

#1


4  

Use java -cp instead of java -jar and put all of you dependencies jars to classpath.

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

Another way is pack all of dependencies to single jar, that allowing you to run application using java -jar.

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

EDIT:

编辑:

In Java *.jar file contains a bulk of classes. When you build your own app, typically, result jar file contains only your classes, but still have to load classes from external libraries you use (so-called dependencies).

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

It can be done two different ways:

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

  1. You create a folder for your application, for example, called lib and place your application jar and all dependencies into. Then you run application using java -cp lib:/\* com.company.Main or (thanks @NilsH, I miss this variant) you make MANIFEST.MF file and specify Main-Class and Classpath attributes inside as described here

    例如,为应用程序创建一个名为lib的文件夹,并将应用程序jar和所有依赖项放在其中。然后使用java -cp lib:/\* com.company.Main或(感谢@NilsH,我想念这个变体)实现应用程序。MF文件,并指定主类和类路径属性

  2. You use special tool (like maven-dependency-plugin if you use maven for build) to pack all classes, either your own, either external to single jar. You got one huge file and can run it using java -jar cliTest.jar.

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

Generally, first approach is preferred and using a MANIFEST.MF file is a good form.

一般来说,首选方法和使用清单。MF文件是一种很好的形式。

#2


3  

Well I should have built the JAR without the sqljdbc4.jar embedded.

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

The second thing I should have run the command like so :

第二,我应该像这样运行命令:

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

.. and then all worked!

. .然后所有的工作!

#3


-1  

Well if you are using maven you could use maven-shade-plugin to include dependent jar's in executable jar the snippet of the pom.xml is given below.

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

#1


4  

Use java -cp instead of java -jar and put all of you dependencies jars to classpath.

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

Another way is pack all of dependencies to single jar, that allowing you to run application using java -jar.

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

EDIT:

编辑:

In Java *.jar file contains a bulk of classes. When you build your own app, typically, result jar file contains only your classes, but still have to load classes from external libraries you use (so-called dependencies).

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

It can be done two different ways:

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

  1. You create a folder for your application, for example, called lib and place your application jar and all dependencies into. Then you run application using java -cp lib:/\* com.company.Main or (thanks @NilsH, I miss this variant) you make MANIFEST.MF file and specify Main-Class and Classpath attributes inside as described here

    例如,为应用程序创建一个名为lib的文件夹,并将应用程序jar和所有依赖项放在其中。然后使用java -cp lib:/\* com.company.Main或(感谢@NilsH,我想念这个变体)实现应用程序。MF文件,并指定主类和类路径属性

  2. You use special tool (like maven-dependency-plugin if you use maven for build) to pack all classes, either your own, either external to single jar. You got one huge file and can run it using java -jar cliTest.jar.

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

Generally, first approach is preferred and using a MANIFEST.MF file is a good form.

一般来说,首选方法和使用清单。MF文件是一种很好的形式。

#2


3  

Well I should have built the JAR without the sqljdbc4.jar embedded.

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

The second thing I should have run the command like so :

第二,我应该像这样运行命令:

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

.. and then all worked!

. .然后所有的工作!

#3


-1  

Well if you are using maven you could use maven-shade-plugin to include dependent jar's in executable jar the snippet of the pom.xml is given below.

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