Проект Java, использующий библиотеку, вызывает NoClassDefFoundError при использовании проекта, использующего ту же библиотеку

Я создаю библиотеку Java для использования в других проектах Java. В проектах используется Repast Symphony, и моя библиотека тоже использует его (поэтому я боюсь, что эта ошибка вызвана некоторыми конфликт). Все строится нормально, но когда я запускаю симуляцию Repast, она выдает java.lang.NoClassDefFoundError: repast/simphony/context/Context

Я попытался экспортировать свою библиотеку в виде jar, импортировать проект напрямую и добавить библиотеку в путь к классам моего проекта, но безрезультатно. Что я могу делать неправильно?

Этот класс Context используется как в моей библиотеке, так и в моих проектах. Ниже приведен фрагмент его использования в двух классах:

// MyContextBulder.java
// This file is in my project
// This class is called by Repast first
import repast.simphony.context.Context;
import repast.simphony.dataLoader.ContextBuilder;
import mylibrary.core.DF;
import mylibrary.core.DF.MyContext;

public class MyContextBuilder implements ContextBuilder<Object> {

    @Override
    public Context<Object> build(Context<Object> context) {

        context.setId("test");
        DF.setContext((MyContext) context);

        // Create agent
        new MyAgent();
        // Add the agent to the Repast context.
        // context.add(t);

        return context;
    }
}
// DF.java
// This file is in my library

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.collections15.Predicate;

import repast.simphony.context.Context;
import repast.simphony.context.ContextListener;
import repast.simphony.space.projection.Projection;
import repast.simphony.util.collections.IndexedIterable;
import repast.simphony.valueLayer.ValueLayer;
import mylibrary.Agent;


/**
 * This static class provides the Directory Facilitator Service
 * and is used to send messages to agents
 * and to keep a directory of all agents in the application.
 * Agents use the static method send(ACLMessage) to send a message
 * to one or more agents. The ACLMessage object contains
 * the receiver agent and the sender (so the receiver can reply back).
 * 
 * This class needs to be setup initially before registering new agents.
 * To do that, simply call setContext(...);
 * @author joaolopes
 *
 */
public class DF {

    private static int lastAID = 0; // Just to help generate new identifiers
    private static HashMap<Integer, Agent> agents; // Contains all agents

    /**
     * The Repast context that contains all
     * scheduled Repast objects.
     */
    private static MyContext context = null;

    /**
     * Registers the agent in the directory and returns its
     * AID (freshly generated for it). If the agent is already
     * registered, returns its current AID.
     * @param agent The agent to be registered
     * @return The AID generated for the agent.
     */
    public static int registerAgent(Agent agent) {
        // If this agent is already in the hashMap,
        // just return its key.
        if (getAgents().containsValue(agent)) {
            return agent.getAID();
        }

        // Quick way to find a new ID for this agent
        // that is not in use at the moment.
        while (getAgents().containsKey(lastAID)) {
            lastAID++;
        }

        // The agent must know their own ID.
        agent.setAID(lastAID);
        agents.put(lastAID, agent);
        System.err.println(context.toString());
        context.add(agent);
        return lastAID;
    }

    public static void setContext(MyContext c){
        context = c;
    }
}

Редактирование для добавления соответствующей информации из комментариев: я не импортирую JAR-файл повторной загрузки непосредственно в свои проекты, как я делаю это в своей библиотеке. Repast Symphony устанавливается в Eclipse как плагин, поэтому я создал «Проекты Repast», включающие все библиотеки Repast. Поэтому я не могу удалить конкретный JAR, который вызывает возможный конфликт классов.


person ecc    schedule 31.03.2014    source источник
comment
Извлеките полученный файл jar и проверьте, есть ли этот класс или нет.   -  person Divers    schedule 31.03.2014
comment
Этот класс «Контекст» не находится в банке моей библиотеки. Он внутри банки Репаста. Содержимое Repast не отображается внутри банок, которые я генерирую. Хотя я не уверен, что понял ваше предложение. Я могу использовать отсутствующий класс в своем проекте библиотеки, но не в проекте, который использует мою библиотеку.   -  person ecc    schedule 31.03.2014


Ответы (2)


Именно так, как вы сказали. Эта ошибка должна быть конфликтом между одними и теми же классами в банке. Если вы используете IDE, попробуйте очистить сборку и заново собрать ее.

А также я бы посоветовал вам использовать только одну банку библиотеки симфонии. Несколько определений классов всегда приводят к неоднозначности для загрузчика классов JVM.

Старайтесь не использовать symphony jar в проекте импорта, так как он уже есть в экспортируемом jar. После импорта вашей библиотеки ошибок не должно быть.

Попробуйте это и дайте мне знать, как это происходит.

Я предлагаю вам использовать инструмент сборки. Что-то вроде Мейвена. Тогда maven с нужным плагином решит эту проблему за вас. Все, что вам нужно сделать, это сказать Maven, что вам нужен определенный файл jar. Тогда произойдет волшебство, и у вас будет хорошо работающий jar-файл для распространения

person Sri777    schedule 31.03.2014
comment
Это, вероятно, лучшее решение, но курс действий для меня не очевиден, потому что мои проекты - это Repast Projects, которые включают все библиотеки разработки repast simphony, а моя библиотека импортирует только основной repast simphony jar. Я не могу удалить отдельную банку из своих проектов. - person ecc; 31.03.2014
comment
@ecc Я использую ant для своих сборок. У меня действительно нет большого представления о maven. Что я делаю в своей сборке, так это копирую все свои банки в один каталог, копирую каталог в конечную банку, помещаю каталог в путь к классам и ссылаюсь на них в проекте. Итак, теперь у меня есть только один файл jar для запуска моего проекта. Использование ANT очень просто. Я могу отправить вам образец файла build.xml, если он вам нужен. - person Sri777; 01.04.2014
comment
У меня нет доступа к внутренностям Repast, как я сказал в предыдущем комментарии, но спасибо за подсказку. - person ecc; 01.04.2014

java.lang.NoClassDefFoundError возникает, когда JVM пытается запустить приложение. Типичные случаи, когда вы получили один jar-файл в качестве «интерфейса». Затем у вас есть другой jar-файл, реализующий этот интерфейс.

Итак, что вам нужно сделать, это иметь банку Repast внутри вашего пути к классам jars. Так что ваша программа может найти правильный класс, который вы хотите использовать.

person Viggo    schedule 31.03.2014
comment
У меня есть манифест в банке моей библиотеки с «Путь к классу: repast.simphony.bin_and_src.jar», но я не уверен, куда мне поместить эту банку. В корне моей библиотечной банки? - person ecc; 31.03.2014
comment
Я предлагаю вам использовать инструмент сборки. Что-то вроде Мейвена. Тогда maven с нужным плагином решит эту проблему за вас. Все, что вам нужно сделать, это сказать Maven, что вам нужен определенный файл jar. Тогда произойдет волшебство, и у вас будет хорошо работающий jar-файл для распространения. - person Viggo; 01.04.2014
comment
Спасибо @Viggo, думаю, пришло время научиться использовать Maven. Если хотите, включите этот комментарий в свой ответ, чтобы я мог его принять. - person ecc; 01.04.2014