我在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的非公共类,其中包含主方法。
看起来您的运行时类路径缺少包含类 org.supercsv.io.ICsvBeanReader 的jar 。
在 疑难杂症 的是,调用一个可执行的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之类的开源依赖项很有用)
显然,如果不存在jar文件,则在运行CC.jar时也会出现类似错误:-)