We're updating the issue view to help you get more done. 

Problem with multiple classloaders and cglib proxy enhancement, e.g. in the usual tomcat configuration

Description

In an usual tomcat classloader configuration, with hibernate3.jar residing in the Tomcat's common class loader and webapplications staying in their own classloaders, the cglib's proxy enhancement fails sometimes, as it tries to load the web application's classes via the Tomcat's common class loader.

The main culprit is the interaction between Hibernate's PojoEntityTuplizer and cglib's AbstractClassGenerator.

PojoEntityTuplizer passes a Set of interfaces to cglib for proxy enhancement. The set is constructed in method buildProxyFactory(PersistentClass, Getter, Setter). Now, depending on the interface classes hash codes, the order of included interfaces varies: sometimes Hibernate's HibernateProxy.class is the first one, sometimes it is the enhanced interface's class.

Problems rise when the Set's iterator gives the interfaces in order of {HibernateProxy.class, InterfaceToBeEnhanced.class}. When performing the enhancing, the cglib chooses the first interface class's classloader to find all the other classes as well. Because HibernateProxy.class was loaded by Tomcat's common class loader, it cannot find the application's class InterfaceToBeEnhanced. Thus a ClassDefNotFoundError is thrown.

There's a JUnit test demonstrating the case. Because the hashCodes of loaded classes is quite undeterministic (read: beyond my skills to make deterministic), I've included ten interface classes that should be cglib-enhanced. Most often, one of these enhancements fails, due to this bug.

A fix would be to change hibernate to prioritize the application's interface classes over Hibernate's HibernateProxy.class in the set. This could be implemented by using LinkedHashSet instead of HashSet, and adding the HibernateProxy.class as the last one. This change does not introduce any faults to existing unit test sets, but allows the attaches JUnit test to run without failures. The attached patch is for Hibernate 3.2.5ga.

Environment

Verified against Hibernate 3.1.3 and Hibernate 3.2.5ga.

Status

Assignee

Brett Meyer

Reporter

Pietu Pohjalainen

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

3.2.5
3.1.3

Priority

Major