Спящий режим в Glassfish — Ejb3Configuration NoClassDefFoundError

Я разместил библиотеки Hibernate как в домене Glassfish, так и в коллекции библиотек моего проекта в Netbeans. hibernate-entitymanager.jar содержит как HibernatePersistence (последний класс в стеке вызовов), так и Ejb3Configuration, поэтому я довольно озадачен тем, почему я получаю ошибку об отсутствующем классе для Ejb3Configuration.

java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.ejb.Ejb3Configuration
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:130)
    at com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:149)
    at com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:84)
...

person Jeff Ferland    schedule 22.05.2009    source источник


Ответы (2)


Я никогда раньше не видел это конкретное сообщение об ошибке, но могу немного объяснить, что оно означает, и указать одну возможную причину.

Линия

java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.ejb.Ejb3Configuration

не означает, что JVM не смогла найти класс org.hibernate.ejb.Ejb3Configuration. Это означает, что JVM может найти этот класс, но она уже пыталась и не смогла загрузить этот класс.

Это текст Could not initialize class ... указывает, что это произошло. Если JVM вообще не сможет найти класс, вместо этого вы получите что-то вроде следующего:

java.lang.NoClassDefFoundError: org/hibernate/ejb/Ejb3Configuration

Кроме того, это также означает, что вы используете Java 6 - в Java 5 соответствующее исключение не имеет сообщения.

Следующие два класса демонстрируют это поведение. Класс Unloadable не может быть загружен, поскольку его статический инициализатор всегда выдает исключение. Мы пытаемся загрузить этот класс, перехватываем результат ExceptionInInitializerError и снова пытаемся загрузить Unloadable.

class Unloadable {
    static {
        if (true) { throw new RuntimeException(); }
    }
}

public class LoadingTest {
    public static void main(String[] args) throws Exception {
        try {
            Class.forName("Unloadable");
        }
        catch (ExceptionInInitializerError e) {
            try {
                Class.forName("Unloadable");
            }
            catch (NoClassDefFoundError e2) {
                System.out.println("XXXXXXXXXXXXXXXXXXXXX");
                e2.printStackTrace(System.out);
            }
        }
    }
}

Когда я запускаю класс LoadingTest, я получаю следующий вывод:

XXXXXXXXXXXXXXXXXXXXX
java.lang.NoClassDefFoundError: Could not initialize class Unloadable
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at LoadingTest.main(LoadingTest.java:14)

Я не могу сказать, почему первоначальная попытка загрузить org.hibernate.ejb.Ejb3Configuration не удалась. Вполне может быть, что сам Ejb3Configuration зависит от классов, отсутствующих в пути к классам. Возможно, стоит просмотреть список всех классов, imported Ejb3Configuration и убедитесь, что все те, у кого нет java.* или javax.*, находятся в JAR-файле, который могут видеть Glassfish и Netbeans.

Кроме того, я могу только предположить, почему JVM пытается загрузить Ejb3Configuration дважды. Когда загрузка класса не удается в первый раз, выдается исключение (обычно это какой-то подкласс LinkageError). Этот тип исключения не часто перехватывается, поэтому я думаю, что происходит что-то вроде следующего:

try {
    // Some code that loads Ejb3Configuration and fails.
}
finally {
    // Some code that also loads Ejb3Configuration and fails.
}

Если код в блоке finally выдает исключение, это исключение заменит любое исключение, выброшенное в блоке try. Я предлагаю это, потому что подобное произошло с этим вопросом. Трассировка стека, опубликованная в этом вопросе, исходит из блока finally.

Если мой ответ по-прежнему вам не помогает, не могли бы вы опубликовать всю трассировку стека, которую вы видите?

person Luke Woodward    schedule 22.05.2009
comment
Похоже, это действительно в конфигурации Log4J, которая не упоминается в трассировке стека, за исключением случаев, когда сервер впервые перезапускается. - person Jeff Ferland; 26.05.2009

У меня тоже была эта проблема, хотя в моем случае это, похоже, проблема конкретной версии. Более новые версии hibernate зависят от Simple Logging Facade для Java (SLF4J), но артефакты maven включают только API, поэтому вам нужны библиотеки времени выполнения в вашей WAR или папке lib на сервере.

Это характерно для версии 3.4.0 Hibernate Entity Manager, хотя может применяться и к другим версиям. Если вы используете Hibernate Core 3.3.x, вы используете Hibernate EM серии 3.4.x, поэтому вам НУЖНЫ эти библиотеки времени выполнения.

person SplinterReality    schedule 06.08.2009