Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring java.lang.LinkageError: loader constraint violation: loader previously initiated loading for a different type with name X

Tags:

java

spring

I am new to Spring and use Spring 3.2.2. I have some beans which I injected via <constructor-arg> which works fine. Now I wanted to inject some bean via @Autowired which totally went wrong. I have done this:

beans.xml:

<context:annotation-config />
<bean id="formulaFactory" class="my.project.formula.impl.GenericFormulaFactory"
    factory-method="getInstance">
<qualifier value="formulaFactory"></qualifier>
</bean>

Java source:

@Autowired
@Qualifier("formulaFactory")
private FormulaFactory formulaFactory;

(Changing the qualifier or leaving it out did not make any difference...)

And I get this error:

java.lang.LinkageError: loader constraint violation: loader (instance of org/springframework/context/support/ContextTypeMatchClassLoader$ContextOverridingClassLoader) previously initiated loading for a different type with name "my/project/formula/FormulaKey"

I wonder why this error comes up. Especially the type FormulaKey irritates me. When I use the @Autowired annotation with some other bean, it works.

I have to mention that I implemented the GenericFormulaFactory as singleton via getInstance method. Maybe that causes some problems?

The application is a stand-alone app. I checked all the jars for duplicity too and I do not assume that this is the cause of the problem because the error relates to my own classes.

Regards, Oliver

UPDATE: I removed the error without knowing what cause it.

What I did:

  1. Remove the getInstance() method and singleton nature of the factory implementation
  2. Added the factory interface to a handler classes constructor (and constructor-arg in xml)

Now I can use the xml to configure the implementation and use it with @Autowired annotations too.

xml:

<bean id="formulaHandler" class="my.project.formula.impl.DefaultFormulaHandler">
    <constructor-arg ref="formulaFactory" />
</bean>
<bean id="formulaFactory" class="my.project.formula.impl.GenericFormulaFactory" />

Still wondering why the error came up in the first place. In the implementation of the factory, a HashMap was created using FormulaKey as key, so maybe this caused trouble. If someone knows the answer, I would really like to know it.

like image 799
4thfloorstudios Avatar asked Aug 08 '13 13:08

4thfloorstudios


1 Answers

Here is what I could gather so far:

  1. The error java.lang.LinkageError comes in a situation when there are two classloaders involved in loading a class.
  2. A classloader keeps track of the classes loaded by generating a unique identifier which contains the fully qualified class name itself and the classloader which loaded it.
  3. When a classloader receives a reference of a class loaded by another class which is already loaded by itself, this results into erroneous situation, as a class can be loaded only once, in a classloading hierarchy.
  4. When custom classloaders are involved, for loading a particular class, the practice is that the parent classloaders are queried first if that class is already loaded.
  5. In the scenario, when a custom classloader does not query the parent hierarchy and decided to load the class itself, there might be case wherein the class being loaded is already loaded by some classloader in parent hierarchy.
  6. Read Kieviet, Frank's "The java.lang.LinkageError: loader constraint violation" demystified" to know more about it.
  7. For your case, I guess the XML configuration and Annotation processing is done by two different classloaders.
  8. In the error scenario, my.project.formula.FormulaKey is loaded by one classloader and then the class loader involved in annotation processing loads it one more time.
  9. When you changed the code, the loading of my.project.formula.FormulaKey is deferred as its no more referred while loading the context from XML .
like image 184
Santosh Avatar answered Nov 14 '22 19:11

Santosh