web-dev-qa-db-fra.com

Qu'est-ce qu'une exception IncompatibleClassChangeError en Java?

je travaille sur une petite application et j'essaie d'utiliser Hibernate Annotations pour mapper mes entités. Je voulais tester si tout allait bien quand j'ai eu cette exception: 

    Exception in thread "main" Java.lang.ExceptionInInitializerError
 at fr.cc2i.intervention.dao.main.Main$HibernateUtil.<clinit>(Main.Java:48)
 at fr.cc2i.intervention.dao.main.Main.test(Main.Java:21)
 at fr.cc2i.intervention.dao.main.Main.main(Main.Java:32)
Caused by: Java.lang.IncompatibleClassChangeError: Implementing class
 at Java.lang.ClassLoader.defineClass1(Native Method)
 at Java.lang.ClassLoader.defineClassCond(ClassLoader.Java:632)
 at Java.lang.ClassLoader.defineClass(ClassLoader.Java:616)
 at Java.security.SecureClassLoader.defineClass(SecureClassLoader.Java:141)
 at Java.net.URLClassLoader.defineClass(URLClassLoader.Java:283)
 at Java.net.URLClassLoader.access$000(URLClassLoader.Java:58)
 at Java.net.URLClassLoader$1.run(URLClassLoader.Java:197)
 at Java.security.AccessController.doPrivileged(Native Method)
 at Java.net.URLClassLoader.findClass(URLClassLoader.Java:190)
 at Java.lang.ClassLoader.loadClass(ClassLoader.Java:307)
 at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:301)
 at Java.lang.ClassLoader.loadClass(ClassLoader.Java:248)
 at fr.cc2i.intervention.dao.main.Main$HibernateUtil.<clinit>(Main.Java:44)
 ... 2 more

Quelqu'un peut-il expliquer quelle est cette exception? C'est la première fois que je le vois. Voici l'essentiel de mon application: 

 package fr.cc2i.intervention.dao.main;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import fr.cc2i.intervention.dao.beans.Client;
import fr.cc2i.intervention.dao.beans.Contrat;

public class Main {

 public static void test(){
  Client c = new Client();
  c.setCode("123343");
  c.setAdresse("fkhdhdmh");
  c.setNom("dgsfhgsdfgs");
  c.setPhone("53456464");
  c.setContrat(new Contrat());

  Session session = HibernateUtil.getSession();
        session.beginTransaction();        
        session.save(c);
        session.getTransaction().commit();

 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  Main.test();

 }

 public static class HibernateUtil {

 private static final SessionFactory sessionFactory;
     static {
         try {
             sessionFactory = new AnnotationConfiguration()
                     .configure().buildSessionFactory();
         } catch (Throwable ex) {
             // Log exception!
             throw new ExceptionInInitializerError(ex);
         }
     }

     public static Session getSession()
             throws HibernateException {
         return sessionFactory.openSession();
     }
 }

}

Ma configuration d'hibernation est très simple: 

    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
  <!-- Database connection settings -->
  <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
  <property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
  <property name="connection.username">sa</property>
  <property name="connection.password"></property>

  <!-- JDBC connection pool (use the built-in) -->
  <property name="connection.pool_size">1</property>

  <!-- SQL dialect -->
  <property name="dialect">org.hibernate.dialect.HSQLDialect</property>

  <!-- Enable Hibernate's automatic session context management -->
  <property name="current_session_context_class">thread</property>

  <!-- Disable the second-level cache  -->
  <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

  <!-- Echo all executed SQL to stdout -->
  <property name="show_sql">true</property>

  <!-- Drop and re-create the database schema on startup -->
  <property name="hbm2ddl.auto">update</property>

  <mapping package="fr.cc2i.intervention.dao.beans.Client" />
  <mapping class="fr.cc2i.intervention.dao.beans.Contrat" />
  <mapping class="fr.cc2i.intervention.dao.beans.Intervention" />
  <mapping class="fr.cc2i.intervention.dao.beans.Technicien" />



 </session-factory>
</hibernate-configuration>

Voici la dépendance d'hibernate maven que j'utilise:

<properties>
        <org.springframework.version>3.0.3.RELEASE</org.springframework.version>
        <hibernate.version>3.6.0.Beta1</hibernate.version></properties>

    <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

Quelqu'un peut m'aider s'il vous plaît ??

17
Dimitri

Cela signifie qu'à un moment donné, une interface a été changée en class, mais qu'un implémenteur de l'interface d'origine n'a pas été modifié ni recompilé pour s'adapter à cette modification (incompatible).

Par exemple, considérons les types suivants:

interface Fooable {
  void foo();
}

class FooImpl implements Fooable {
  public void foo() {
     /* Do something... */
  }
}

Supposons maintenant que Fooable soit modifié et recompilé, mais que FooImpl soit pas :

abstract class Fooable {
  public abstract void foo();
}
25
erickson

Le support de JDK 1.4 a été abandonné en 3.6. Ainsi, Hibernate Annotations a été fusionné dans Core et il n’est plus nécessaire d’avoir à la fois Configuration et AnnotationConfiguration et le dernier ne doit pas être utilisé dans 3.6.x (en fait, vous devriez probablement utiliser JPA EntityManager, pas l’API principale, est une autre histoire).

Mais mon vrai conseil serait d’utiliser la branche .5.x de Hibernate, pas la 3.6.x. Comme nous l'avons déjà vu, l'équipe d'Hibernate introduit de gros changements dans la version 3.6, qui est encore en version bêta, et si vous ne suivez pas les changements de près, vous ferez face à des surprises et vous ne trouverez pas beaucoup de ressources sur Internet. encore. Utilisez simplement Hibernate 3.5 (3.5.5-Final au moment de la rédaction de ce document).

4
Pascal Thivent

Vérifiez si toutes vos bibliothèques sont compatibles. Essayez la même chose avec une version stable de Hibernate, il est possible que la version bêta soit défectueuse ou que la version bêta de Hibernate 3.6.0 ait des dépendances incompatibles.

Essayez de le construire sans maven et avec les bibliothèques hibernate 3.6.0 beta1 des serveurs officiels.


OK - votre problème n'est pas un bug mais une nouvelle fonctionnalité. Les notes de publication pour Hibernate 3.6.0 Beta2 indiquent un changement majeur par rapport à la version bêta précédente: AnnotationConfiguration est maintenant totalement obsolète . Vous devez donc (a) mettre à jour la dernière version bêta (Beta3) si vous souhaitez conserver une version 3.6.0 et (b) ne pas continuer à utiliser AnnotationConfiguration.

3
Andreas_D

Oui, erickson a correctement identifié le problème.

Cela est probablement dû à la présence de deux versions en conflit de la même définition de type dans votre chemin d'accès aux classes. Par exemple, bibliothèque-version2.jar définit certaines choses, mais vous avez également bibliothèque-version5.jar dans votre chemin de classe.

Au moment de l'exécution, cela entraîne la douleur et la souffrance décrites par erickson.

2
RonU

J'écris ceci pour aider celui qui cherche cette erreur. Parfois, les fichiers jar provenant de Spring Roo généraient pom.xml et les bibliothèques Tomcat Server Runtime en conflit et produisaient cette erreur lors des tests unitaires. Lors de la création d'une technologie frontale telle que Flex, il n'est pas nécessaire que les bibliothèques d'exécution du serveur soient présentes dans le chemin d'accès aux classes. Supprimez donc simplement les bibliothèques d'exécution serveur du chemin d'accès aux classes.

1
zawhtut

Quel serveur d'applications utilisez-vous? Peut-être un bocal en veille ou en double en conflit.

0
Julian Bonilla