【问题标题】:Cannot find Main Class in File Compiled With Ant在用 Ant 编译的文件中找不到主类
【发布时间】:2011-03-09 18:50:00
【问题描述】:

我在 Eclipse 中编译并运行我的程序,一切正常,但是当我用 Ant 打包并运行它时,我得到了这个错误:

Exception in thread "main" java.lang.NoClassDefFoundError: org/supercsv/io/ICsvB
eanReader
Caused by: java.lang.ClassNotFoundException: org.supercsv.io.ICsvBeanReader
        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)
Could not find the main class: jab.jm.main.Test. Program will exit.

请注意,这是 运行时 错误,而不是 Ant 的 编译器错误

我过去构建的这个项目有 0 个问题,现在当我将第二个包添加到我的 lib 文件夹时,它突然对我起作用

这是构建文件供参考:

<?xml version="1.0" ?>

<project name="ServerJar" default="dist" basedir=".">
 <description>
  Builds client files into .jar
 </description>
 <!-- [build variables] -->
 <property name="src" location="src" />
 <property name="build" location="build" />
 <property name="dist" location="dist" />
 <property name="lib" location="lib" />
 <!-- [path to packages] -->
 <path id="master-classpath">
     <fileset dir="${lib}">
         <include name="*.jar"/>
     </fileset>
 </path>


 <target name="init">
  <!-- makes time stamp to be used in jar name -->
  <tstamp />
  <!-- creates build directory structure -->
  <mkdir dir="${build}" />
 </target>

 <target name="compile" depends="init" description="Compiles the source">
  <!-- compiles the java code from ${src} into ${build} -->
  <!-- <javac srcdir="${src}" destdir="${build}" /> -->
  <javac destdir= "${build}">
      <src path="${src}"/>
      <classpath refid="master-classpath"/>
  </javac>
 </target>

 <target name="dist" depends="compile" description="Generates distributable">
  <!-- creates the distribution directory -->
  <mkdir dir="${dist}/lib" />

  <!-- puts everything in ${build} into the jar file -->
  <jar jarfile="${dist}/lib/CC-${DSTAMP}.jar" basedir="${build}">
   <manifest>
    <attribute name="Main-Class" value="jab.jm.main.Test" />
   </manifest>
  </jar>

  <!-- makes a jar file for quick test execution -->
  <jar jarfile="${dist}/lib/CC.jar" basedir="${build}">
   <manifest>
    <attribute name="Main-Class" value="jab.jm.main.Test" />
   </manifest>
  </jar>
 </target>

 <target name="clean" description="Cleans up the extra build files">
  <!-- deletes the ${build} and ${dist} directories -->
  <delete dir="${build}" />
  <delete dir="${dist}" />
 </target>
</project>

提前感谢您的帮助!

编辑:

这是我的主类的构造(这不是实际文件,但这是我的基础)。对于 java 程序,这种结构非常奇怪,可能会给 Ant 带来一些问题。关于如何重建它的任何建议?尝试将其分成多个部分时,我遇到了一堆错误。我以前从未见过这样的构造(是的,我了解它是如何工作的(编译时也是如此),但 Ant 可能不喜欢它)。

import java.io.FileReader;
import java.io.IOException;

import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.ParseDate;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.constraint.Unique;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;

class ReadingObjects {
    static final CellProcessor[] userProcessors = new CellProcessor[] {
        new Unique(new StrMinMax(5, 20)),
        new StrMinMax(8, 35),
        new ParseDate("dd/MM/yyyy"),
        new Optional(new ParseInt()),
        null
    };

    public static void main(String[] args) throws Exception {
        ICsvBeanReader inFile = new CsvBeanReader(new FileReader("foo.csv"), CsvPreference.EXCEL_PREFERENCE);
        try {
          final String[] header = inFile.getCSVHeader(true);
          UserBean user;
          while( (user = inFile.read(UserBean.class, header, userProcessors)) != null) {
            System.out.println(user.getZip());
          }
        } finally {
          inFile.close();
        }
   }
}

public class UserBean {
    String username, password, town;
    Date date;
    int zip;

    public Date getDate() {
        return date;
    }
    public String getPassword() {
        return password;
    }
    public String getTown() {
        return town;
    }
    public String getUsername() {
        return username;
    }
    public int getZip() {
        return zip;
    }
    public void setDate(final Date date) {
        this.date = date;
    }
    public void setPassword(final String password) {
        this.password = password;
    }

    public void setTown(final String town) {
        this.town = town;
    }
    public void setUsername(final String username) {
        this.username = username;
    }
    public void setZip(final int zip) {
        this.zip = zip;
    }
}

注意这个类的名字实际上是 UserBean,它包含一个名为 ReadingObjects 的非公共类,其中包含 main 方法。

【问题讨论】:

  • 你能在 ant 创建的 jar 上运行 'jar -tf' 并发布结果吗?
  • 你能解释一下“当我将第二个包添加到我的 lib 文件夹时,它突然对我起作用了吗?”
  • @Rancidfishbreath: 我刚刚得到:['jar' 不是内部或外部命令、可运行程序或批处理文件。] 我在网上找不到任何可靠的解决方案,但我相信它与将 JDK 添加到我的 Path 变量有关吗? @Romain:我在我的 lib 文件夹和构建路径中添加了第二个 .jar 文件。就在那时,它开始发挥作用。在那之前一切都很好。我可能忘记了别的东西,但我只记得这些。

标签: java eclipse ant csv jar


【解决方案1】:

您是否尝试在运行 jar 时显式指定类路径,以确保新库在其上?

也许库 1 存在于默认类路径中,因此您的项目运行良好,直到您添加了库 2,而库 2 不存在。在 Eclipse 中运行时,IDE 可能会自动为您将库 2 添加到类路径中。您可以在 Eclipse 中检查项目的运行配置中的类路径,并确保在不通过 IDE 运行时包含其中的所有内容。

【讨论】:

    【解决方案2】:

    您的运行时类路径似乎缺少包含类 org.supercsv.io.ICsvBeanReader 的 jar。

    gotcha 是在调用可执行 jar 时不能从命令行设置类路径。您必须在清单中进行如下设置:

    <target name="dist" depends="compile" description="Generates distributable">
        <!-- creates the distribution directory -->
        <mkdir dir="${dist}/lib" />
    
        <!-- Remove manifest. This jar will end up on the classpath of CC.jar -->
        <jar jarfile="${dist}/lib/CC-${DSTAMP}.jar" basedir="${build}"/>
    
        <!-- Fancy task that takes the pain out creating properly formatted manifest value -->
        <manifestclasspath property="mf.classpath" jarfile="${dist}/lib/CC.jar">
            <classpath>
                <fileset dir="${dist}/lib" includes="*.jar"/>
            </classpath><!--end tag-->
        </manifestclasspath>
    
        <!-- This is the executable jar -->
        <jar jarfile="${dist}/lib/CC.jar" basedir="${build}">
            <manifest>
                <attribute name="Main-Class" value="jab.jm.main.Test"/>
                <attribute name="Class-Path" value="${mf.classpath}"/> 
            </manifest>
        </jar>
    
    </target>
    

    这种方法将允许您按如下方式运行 jar:

    java -jar CC.jar
    

    如果没有额外的清单条目,您必须按如下方式运行 jar:

    java -cp CC.jar:CC-DSTAMPVALUE.jar jab.jm.main.Test
    

    注意

    只有 CC.jar 是可执行的并且需要特殊的清单。使用这种模式意味着将来放置到 lib 目录中的其他 jar 将自动包含在运行时类路径中。 (对于像 log4j 这样的开源依赖很有用)

    显然,在运行 CC.jar 时,如果 jar 文件不存在,您会收到类似的错误 :-)

    【讨论】:

    • 您在上面的帖子中提到最近引入了额外的jar?该额外的 jar 需要包含在 CC.jar 的清单“CLass-Path”条目中。我会更新我的帖子
    • 午饭后我会看看这个。非常感谢!
    • 没关系。我犯了一个错误。我的主要方法现在在 ExcelFile 中,我在 build.xml 中更改了它,但仍然出现错误。新错误:“线程“main”中的异常 java.lang.NoSuchMethodError:main”。主要肯定存在。我现在正在上传我的主要课程(这可能是问题 - 结构......奇怪)。
    • 我切换回旧的 build.xml 并得到同样的新错误 =/
    • @hfontanez 点了。我通常通过使用 Apache ivy 来管理我的 3rd 方依赖项来避免这个问题。
    【解决方案3】:

    这可能是由于生成的类文件的位置而发生的。即,当您通过 Eclipse 构建时,它会在指定为 ex:bin 的输出文件夹的位置生成类文件,并在运行时查看该位置的类文件。

    因此请检查您的 ant 是否在与 BuildPath 配置中提到的输出文件夹相同的位置生成类文件。如果不是将输出文件夹位置更改为您的 ant 生成类文件的位置

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多