Не удается найти основной класс в файле, скомпилированном с помощью Ant - PullRequest
1 голос
/ 29 июня 2010

Я компилирую и запускаю свою программу в 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>

Заранее спасибо за помощь!

EDIT:

Вот как выглядит конструкция для моего основного класса (это не фактический файл, а то, на чем я основываю свой). Конструкция очень странная для 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, который содержит основной метод.

Ответы [ 3 ]

12 голосов
/ 30 июня 2010

Похоже, что в вашем пути к классам во время выполнения отсутствует файл jar, содержащий класс org.supercsv.io.ICsvBeanReader .

gotcha заключается в том, что вы не можете установить classpath из командной строки при вызове исполняемого файла 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>

Этот подход позволит вам запустить банку следующим образом:

java -jar CC.jar

Без дополнительной записи манифеста вы должны запуститьбаночка выглядит следующим образом:

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

Примечание

Только CC.jar является исполняемым и требует специального манифеста.Использование этого шаблона означает, что будущие дополнительные файлы jar, помещенные в каталог lib, будут автоматически включены в путь к классам во время выполнения.(Полезно для зависимостей с открытым исходным кодом, таких как log4j)

Очевидно, что при запуске CC.jar вы получите похожую ошибку, если jar-файлы отсутствуют: -)

0 голосов
/ 30 июня 2010

Это может происходить из-за расположения сгенерированных файлов классов.т. е. когда вы создаете сквозное затмение, оно генерирует файлы классов в месте, указанном в качестве выходной папки для ex: bin, и во время работы просматривает это место для файлов классов.

Так проверьте,ant генерирует файлы классов в том же месте, что и выходная папка, указанная в конфигурации BuildPath.Если нет , измените местоположение выходной папки на местоположение, где ваш муравей генерирует файлы классов .

0 голосов
/ 29 июня 2010

Вы пытались явно указать classpath при запуске jar, чтобы убедиться, что на нем установлена ​​новая библиотека?

Возможно, библиотека 1 присутствует в пути к классам по умолчанию, поэтому ваш проект работал нормально, пока вы не добавили библиотеку 2, которой не было. При работе в Eclipse среда IDE может автоматически добавлять библиотеку 2 в путь к классам. Вы можете проверить classpath в Run Configuration вашего проекта в Eclipse и убедиться, что вы включаете все, что есть, когда не запускаетесь через IDE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...