在使用 Ant 编译的文件中找不到主类
我在 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 方法。
I compile and run my program in Eclipse and everything works fine, but when I package it with Ant and run it, I get this error:
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.
Note that this is a runtime error and not a compiler error with Ant.
I've built this project in the past with 0 issues and now it suddenly acts up on me when I add a second package to my lib folder?
Here's the build file for reference:
<?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>
Thanks in advance for the help!
EDIT:
Here's what the construction for my main class looks like (this is not the actual file, but this is what I based mine on). The construction is very odd for a java program and might be giving Ant some issues. Any recommendations on how to reconstruct this? I got a bunch of errors when trying to separate this into multiple parts. I've just never seen a construction like this before (yes, I understand HOW it works (and it does when compiled), but Ant might not like it).
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;
}
}
Notice how the class's name is actually UserBean and it contains a non-public class named ReadingObjects within it that holds the main method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来您的运行时类路径缺少包含类 org.supercsv.io.ICsvBeanReader 的 jar。
问题是调用可执行 jar 时无法从命令行设置类路径。您必须按如下方式在清单中设置它:
此方法将允许您按如下方式运行 jar:
如果没有额外的清单条目,您必须按如下方式运行 jar:
注意
只有 CC.jar 是可执行的,并且需要特殊的清单。使用此模式意味着将来放置到 lib 目录中的其他 jar 文件将自动包含在运行时类路径中。 (对于像 log4j 这样的开源依赖项很有用)
显然,当运行 CC.jar 时,如果 jar 文件不存在,你会得到类似的错误:-)
Looks like your runtime classpath is missing the jar containing the class org.supercsv.io.ICsvBeanReader.
The gotcha is that you cannot set the classpath from the command-line when calling an executable jar. You have to set it within the manifest as follows:
This approach will allow you to run the jar as follows:
Without the extra manifest entry you have to run the jar as follows:
Note
Only the CC.jar is executable and needs the special manifest. Using this pattern means future additional jars, placed into the lib directory, will be automatically included in the run-time classpath. (Useful for open source dependencies like log4j)
Obviously, when running the CC.jar you'll get a similar error if the jar files are not present :-)
您是否尝试在运行 jar 时显式指定类路径,以确保新库位于其中?
也许库 1 存在于默认类路径中,因此您的项目运行良好,直到您添加了不存在的库 2。在 Eclipse 中运行时,IDE 可能会自动将库 2 添加到类路径中。您可以在 Eclipse 中检查项目运行配置中的类路径,并确保在不通过 IDE 运行时包含其中的所有内容。
Have you tried explicitly specifying the classpath when running the jar, in order to ensure the new library is on it?
Perhaps library 1 is present in the default classpath, so your project ran fine until you added library 2, which was not present. When running within Eclipse, the IDE may be automatically adding library 2 to the classpath for you. You can check the classpath in your project's Run Configuration within Eclipse, and make sure you are including everything there when not running via the IDE.
发生这种情况的原因可能是生成的类文件的位置。即,当您通过 Eclipse 构建时,它会在指定为 ex: bin 的输出文件夹的位置生成类文件,并且在运行时会在该位置查找类文件。
因此,请检查您的 ant 是否在与 BuildPath 配置中提到的输出文件夹相同的位置生成类文件。如果不是,将输出文件夹位置更改为 ant 生成类文件的位置。
This might be happening because of the location of the generated class files. ie when you build a through eclipse it generates the class files in the location which is specified as the Output folder for ex: bin, and while running it looks at this location for the class files.
So check whether your ant is generating the class files at the same location as the output folder mentioned in the BuildPath configuration. If not change the output folder location to the location where your ant is generating the class files.