Java NoClassDefFoundError with Ant

2019-05-30 10:53发布

问题:

I have a third-party .jar file in a res/lib folder. The ANT build.xml looks like this:

<?xml version="1.0"?>
<project name="my.project" basedir="." default="build">
    <property name="src.dir" value="src"/>
    <property name="build.dir" value="build/classes"/>

    <path id="master-classpath">
        <fileset dir="res/lib">
            <include name="*.jar"/>
        </fileset>
        <pathelement path="${build.dir}"/>
    </path>

    <target name="build">
        <mkdir dir="${build.dir}"/>
        <javac destdir="${build.dir}" optimize="true">
            <src path="${src.dir}"/>
            <classpath refid="master-classpath"/>
        </javac>
    </target>
</project>

The .java file is the following:

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;

public class IO {
    public static void readCSVFile(File file) throws IOException {
        FileReader in = new FileReader(file);
        Iterable<CSVRecord> record = CSVFormat.DEFAULT.parse(in);
    }
}

The compile is OK, but I got a runtime error: java.lang.NoClassDefFoundError: org/apache/commons/csv/CSVFormat. I think something is wrong with the classpath, but it seems ok to me.

UPDATE:

It is running if I use java -cp path;. Main. I have tried to write an ANT script to run it:

<target name="run">
    <java classname="Main">
        <classpath refid="master-classpath"/>
    </java>
</target>

I write ant run in the command line, I get BUILD SUCCESSFUL and nothing happens.

回答1:

Your buildfile compiles your code and includes the third-party Jar in the classpath so that the compiler could be able to locate the classes on which your code depends (e.g. org.apache.commons.csv.CSVRecord).

Similarly, when running your main class via the java your JVM needs to know where the third-party classes exist. Otherwise the classloader will fail to load these classes. So in your example, you should still call the main class as follows:

java -cp pathtoyourlib;. Main

In other words, these are two different "classpath" concepts: one classpath is used by the compiler to know where to locate every referenced class in every class to be compiled, while the other is used by the JVM to know where to load classes when they are dynamically invoked.



回答2:

You state that the compile is ok, but you don't show how you're running the java program..... So to be clear, ANT completes without error? This is a problem running the java program post compilation from the command line?

If I'm correct then there are two problems:

  1. Your java program has no main class (required then running from commandline)
  2. The jars your program depends on my be included on the classpath when running the java program.


回答3:

Your class has no (visible) main method

public static void main(String[] args){
    IO.readCSVFile(File file)
}

You need to pass the classpath when running the file

java -cp yourclasspath