Understand this error:
This is a java.lang.LinkageError
error which happens when jvm tries to link the loaded classes. Note that the code is firstly compiled(with the dependent classes), then all involved classes are loaded by the jvm, and then these classes are linked together.
Think about the error:NoSuchField
, it means when linking the target class, the field is not there. But when compiling, the class should have that field, otherwise the code cann't compile. When linked, the jvm finds that that field is not there. So the only reason is that we are compiling with a class with that field, and another version of that class(which doesnot have that field) is loaded and linked.
Decide your situation between two common reasons for this error
Usually the wrongly loaded class is either a source code you have modified, or a class in one of your dependent jar package. We can decide this by finding the wrongly loaded class by adding -verbose:class
argument to the jvm which is trying to run your application, in your ide. This argument print all the loaded classes in the console. In eclipse we place it in : right click on your project-> run as-> run configurations->the arguments
tag->VM argument
field.
After you find the wrongly loaded class, usually it is either a class that you have the source code in your project, or it is in a jar package that your project is depending on.
Different situation leads to different solutions.
Solution for the source code case:
Chances are that you changed that class(adding the field in the source code), but did not recompile it. It may due to different reasons, but you should delete the old version compiled .class
file of that class, and recompile it to let the new version .class
file contain that field.
Solution for the jar package case:
You should try to let the project load the correct jar package. But why a different version is envolved is usually because that they are both depended(by different parts of your project). The situation is much simple(and may not exists in the real world project ), if you write codes taht directly depend on both of them, just choose one and drop another.
But chances are that your code indirectly depend on them. And you don't want to change your code(or change as less as possible).
One solution is that you write your own ClassLoader
to paly with both:Possible to use two java classes with same name and same package? (I didn't try it)
If you choose to load the correct version(that containing such field
), and your code that indirectly depending on the wrong
version still can work(hopingfully), then we have a much simpl solution: let your project choose the right version.
Take eclipse for example, you can use the Order and Export
tag in your Java Build Path
property, just adjust the order to let the correct version be ahead of the wrong
version, since the fucntion of Order
part is :
On one hand, it functions as the order of resolution for resources
used in the building of the project in question (the "Order" part).
If the correct version or the wrong version does not show up there, you should determine what package is depending on it and adjust its order, due to the function of Export
part . Read The "Order and Export" tab in "Java Build Path" for details.