NoSuchFieldError Java

Viewed 73127

I am getting a NoSuchFieldError in my code, now oracle isn't very clear about why this error is thrown only saying: this error can only occur at run time if the definition of a class has incompatibly changed.

Can someone explain to me how one could 'incompatibly change' a class? The class I am talking about extends quite allot of classes so I suspect it might have to do with that but I don't know where to start looking or what I'm looking for.

7 Answers

Although the underlying cause is the same as described in the top answers, my problem was a bit different than the other answers that I've found here so I thought I'd share.

I'm working on a large project that has several maven poms spread out throughout the project. A colleague updated the version number of one of the dependencies without updating every single place where that dependency appeared, resulting in mismatched libraries on the classpath.

The solution was to update each occurrence of this dependency to have to same version number. As a side note, to prevent this from happening again we added a variable there and now we control the version number of those dependencies from one spot.

It was quite tricky for me, so I am writing my solution.

I was working in IntelliJ with Boot everything was fine, all Java 8 versions were set up appropriately.

After some hours I somehow checked on terminal the javac -version and guess what, it was set to version 9. So make sure to look for javac, I know its counterintuitive but supposedly, since I had set the jdk on bash profile, on IntelliJ etc, I shouldn't have to bother of it.

Hope it helps!

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.

Related