2013-11-03 48 views
10

我刚刚开始构建Java应用程序(我确实有.NET体验),并且正在尝试构建一个小测试应用程序,其整个代码如下:ClassNotFoundException在运行JAR时,在IntelliJ IDEA中运行时没有错误

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)所得到的JAR是脂肪(550KB的sqljdbc4.jar,包括在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:基于尼古拉的答案,我已经做了以下内容:

  1. 删除现有的神器
  2. 创建一个新的神器,像这样:

enter image description here

enter image description here

.. a ND导致这样的:

enter image description here

  • 生成 - >生成伪像 - > cliTest.jar - >重建

  • CMD提示在包含文件夹:

  • [cliTest.jar 566 KB生成]

    Java的罐子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) 
    

    回答

    3

    嗯,我应该建立了没有嵌入sqljdbc4.jar的JAR。

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

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

    ..然后所有的工作!

    +0

    这是一种方法。但是,将每个类文件嵌入到一个jar中也应该可行。请注意,jar文件实际上是zip文件,因此您可以随时打开它们并查看它们是否包含所有类。 – lbalazscs

    +0

    是的,我查看了依赖JAR(sqljdbc4.jar),但试图将它嵌入到我的结果JAR中,就会在问题的最后部分产生SecurityException。我猜想嵌入的JAR是被签名的,其​​中包含的JAR不是......或类似的东西。 –

    +0

    是的,如果您将签名的jar文件的所有文件嵌入大容器中,签名可能会导致问题。您可以删除META-INF/* .SF,META-INF/* .DSA和META-INF/* .RSA文件以消除签名。 – lbalazscs

    4

    使用java -cp代替java -jar,并把所有的依赖关系,你罐子类路径。

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

    编辑:

    在Java * .jar文件包含了大部分的类。当您构建自己的应用程序时,通常,结果jar文件仅包含您的类,但仍需从您使用的外部库(所谓的依赖关系)加载类。

    这是可以做到两种不同的方式:

    1. 您为应用程序创建一个文件夹,例如,被称为lib,把你的应用程序的jar和所有依赖成。然后运行使用java -cp lib:/\* com.company.Main或应用程序(感谢@NilsH,我错过这个变体)你让MANIFEST.MF文件并指定Main-ClassClasspath中的属性描述here

    2. 您可以使用特殊的工具(如Maven的依赖,插件,如果你使用maven for build)来打包所有的类,无论是你自己的,还是外部的单个jar。你有一个巨大的文件,可以运行它使用java -jar cliTest.jar

    通常,第一种方法是优选的,并且使用MANIFEST.MF文件是一种很好的形式。

    +0

    好的,但我仍然构建JAR或不? –

    +0

    是的,我已经解释了我的答案。 – Nikolay

    +0

    我不得不不同意。构建可执行jar的“正确”方法是在jar文件的META-INF文件夹中有一个合适的MANIFEST.MF文件,并使用'java -jar'运行它。除了清单的Main-Class属性之外,'MANIFEST.MF'文件还应包含'Class-Path'部分中相关JAR的条目。 – NilsH

    -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>