This started to happen to me and all my teammates at some point and we cannot figure out what is that triggered that and how to solve that.
We all have the same Java projects in our workspaces. In Project
menu we all have Build automatically
ticked.
Let's say that my workspace has no compilation errors. I make a trivial change to one of the Java classes, I save, Eclipse starts rebuilding and the result is that hundreds of classes - in more than one project - have now compilation errors. That is because for some reason a lot of import
statements now show the error The import [xxx] cannot be resolved.
But those import
s (and the whole workspace for that matter) were perfectly error-free before I saved my trivial, completely unrelated change, and they all go back to being perfectly error-free if at this point I just do Project / Clean
which of course triggers a workspace rebuild.
The .log
file in the workspace folder doesn't show anything; if it's empty before I save, it's still empty after my save caused those errors to appear.
This is way more annoying than it might sound, because building the whole workspace can take minutes, and since a mere Project / Clean
makes all failing import
s work again this cannot be due to something wrong in our code.
I know this is a long shot but considering how reproducible this issue is for us (100% of the times on 100% of the several computers involved) maybe someone else had the same problem and discovered the cause or a solution.
The version is Eclipse Java EE IDE for Web Developers, Mars.1 Release (4.5.1), on Windows 8.
We use Gradle (2.6) by creating External Tool Configurations that point to gradlew.bat
and with a string prompt. We run those manually to configure the projects after importing them into Eclipse (by entering eclipse
in the string prompt) and to build the JARs for the deployment (by entering build
in the string prompt), however I don't think Gradle is involved in the problematic build by Eclipse.
ADDED: I'm no longer sure it's accurate to say that this problem is 100% reproducible, because the following happens:
Initial state: no errors present (which can only be because I cleaned all projects) and no unsaved changes.
I make a change to a class in the editor, I save and that generates the errors.
I undo that change, save and clean; so I'm back to exactly the initial state.
I redo that change (identical), I save and this time I don't get the errors.
ADDED: Using javap
to inspect the generated .class
files, I notice the 2 following things:
1) Minor and major versions are always the same no matter the .class
file got built with the errors or without (minor version: 0; major version: 51). Of course when the .class
file is built with the errors it contains the error messages while when it's built without the errors it doesn't contain the error messages.
2) Comparing the outputs of javap
for both .class
files, I see that in the "Constant pool" section the lines are identical (showing names of class members and objects, f.ex. Ljava/lang/String;
) up until a line about a class my.package.MyClassImpl
where the problematic .class
file has
#32 = Utf8 LMyClassImpl;
and the correct .class
file has the same but fully qualified:
#32 = Utf8 Lmy.package.MyClassImpl;
I'm sure this has to do with the problem.
ADDED: The problem disappears if I tick the “Rebuild class files modified by others” checkbox in Eclipse preferences under Java / Compiler / Building / Output folder
. At least all the cases where a certain change was showing the problem don't show it any longer.
This is just a workaround and I'm keeping investigating the root cause, however this hints strongly towards Eclipse’s internal Java compiler playing a major role in this problem.
ADDED: Below is the content of the .classpath
and .project
files of two of the projects. The first project is one that shows those compilation errors. The second project is one that never does. I had to replace many lines with ....
in one file because of the 30.000 chars limit and I can't seem to be able to find how to attach files; if that is allowed and someone points me to how to do that I will attach them without cuts and remove their content from the question.
Note the interesting difference that the first .classpath
has an entry excluding="**/*.class"
and the second doesn't. However when I modify the Java Build Path of all the projects that have that through Eclipse (Project Properties / Java Build Path / Source) removing their excluded:**/*.class
the resulting .classpath
files don't have that entry but the compilation errors appear anyway (also after restarting Eclipse). And if I do the opposite (i.e. add excluded:**/*.class
to all projects that don't have it) then the .classpath
files of all the projects get that entry but the compilation errors still show up. I would have bet that this would solve the problem but it doesn't.
MyProjectThatGetsErrors
: .project
file:
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyProjectThatGetsErrors</name>
<comment/>
<projects/>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments/>
</buildCommand>
</buildSpec>
<linkedResources/>
</projectDescription>
MyProjectThatGetsErrors
: .classpath
file:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/*.class" kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path="/MyUtilsProject1"/>
<classpathentry kind="src" path="/MyUtilsProject2"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/org.eclipse.jetty/jetty-io/8.1.15.v20140411/8849cf59187275366cd05f37b2fb71319291370b/jetty-io-8.1.15.v20140411.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/org.eclipse.jetty/jetty-io/8.1.15.v20140411/49fd78caf4ca0c7cdbc532fc48ff46183bb8fb62/jetty-io-8.1.15.v20140411-sources.jar"/>
....
....
<classpathentry kind="lib" path="D:/EclipseMars/git/MyProjectThatGetsErrors/lib/tapestry5-highcharts-1.2.0.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
MyUtilsProject1
: .project
file:
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>MyUtilsProject1</name>
<comment/>
<projects/>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments/>
</buildCommand>
</buildSpec>
<linkedResources/>
</projectDescription>
MyUtilsProject1
: .classpath
file:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-digester/commons-digester/1.8/dc6a73fdbd1fa3f0944e8497c6c872fa21dca37e/commons-digester-1.8.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-digester/commons-digester/1.8/6c296de7dc352e0af9a40f92f5af995314d41fc9/commons-digester-1.8-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.3.2/90a3822c38ec8c996e84c16a3477ef632cbc87a3/commons-lang3-3.3.2.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.3.2/d2a489573c0ed2c4942b3660decad5d65087b406/commons-lang3-3.3.2-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-configuration/commons-configuration/1.6/32cadde23955d7681b0d94a2715846d20b425235/commons-configuration-1.6.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-configuration/commons-configuration/1.6/2d24067548bf9022d03cfd6ca302e1f6c5d4936/commons-configuration-1.6-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-fileupload/commons-fileupload/1.2/a10c06183fe21f3bb3dda3b5946b93db6e2ad5cc/commons-fileupload-1.2.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-fileupload/commons-fileupload/1.2/c7859b375ae5bc1b4a4f2b91ce6d1d387e676e61/commons-fileupload-1.2-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-beanutils/commons-beanutils-core/1.8.0/175dc721f87e4bc5cc0573f990e28c3cf9117508/commons-beanutils-core-1.8.0.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/org.apache.velocity/velocity/1.7/2ceb567b8f3f21118ecdec129fe1271dbc09aa7a/velocity-1.7.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/org.apache.velocity/velocity/1.7/eb11eb70171ed64842b2e5216d5904e21ed162ac/velocity-1.7-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-collections/commons-collections/3.2.1/761ea405b9b37ced573d2df0d1e3a4e0f9edc668/commons-collections-3.2.1.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-collections/commons-collections/3.2.1/fa095ef874374e5b2a11f8b06c26a5d68c7cb3a4/commons-collections-3.2.1-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-beanutils/commons-beanutils/1.7.0/5675fd96b29656504b86029551973d60fb41339b/commons-beanutils-1.7.0.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-beanutils/commons-beanutils/1.7.0/b68c4fc66026e8c08df7fb57c7dc1e94a6ed8cbb/commons-beanutils-1.7.0-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-lang/commons-lang/2.4/16313e02a793435009f1e458fa4af5d879f6fb11/commons-lang-2.4.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-lang/commons-lang/2.4/2b8c4b3035e45520ef42033e823c7d33e4b4402c/commons-lang-2.4-sources.jar"/>
<classpathentry kind="lib" path="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/5043bfebc3db072ed80fbd362e7caf00e885d8ae/commons-logging-1.1.1.jar" sourcepath="C:/Users/Me/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/f3f156cbff0e0fb0d64bfce31a352cce4a33bc19/commons-logging-1.1.1-sources.jar"/>
<classpathentry kind="lib" path="D:/EclipseMars/git/MyUtilsProject1/lib/MyCompany cayenne-client-3.0.2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
ADDED: When I switch to a different Git branch or pull changes into my workspace, which of course causes those compilation errors to appear, sometimes Eclipse shows an error dialog about a NullPointerException
in the Java Builder, and in that case it does write it in the log (see stacktrace below). However 99% of the times when those errors show up there is no such null pointer.
!ENTRY org.eclipse.core.resources 4 75 2015-11-10 13:51:31.544
!MESSAGE Errors occurred during the build.
!SUBENTRY 1 org.eclipse.jdt.core 4 75 2015-11-10 13:51:31.544
!MESSAGE Errors running builder 'Java Builder' on project 'MyProject'.
!STACK 0
java.lang.NullPointerException
at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding$2.compare(ReferenceBinding.java:92)
at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding$2.compare(ReferenceBinding.java:1)
at java.util.TimSort.binarySort(TimSort.java:265)
at java.util.TimSort.sort(TimSort.java:208)
at java.util.Arrays.sort(Arrays.java:727)
at org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding.sortFields(ReferenceBinding.java:217)
at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.fields(BinaryTypeBinding.java:946)
at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.fields(ParameterizedTypeBinding.java:458)
at org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding.getField(ParameterizedTypeBinding.java:643)
at org.eclipse.jdt.internal.compiler.lookup.Scope.findField(Scope.java:1371)
at org.eclipse.jdt.internal.compiler.ast.FieldDeclaration.resolve(FieldDeclaration.java:194)
at org.eclipse.jdt.internal.compiler.lookup.FieldBinding.constant(FieldBinding.java:215)
at org.eclipse.jdt.internal.compiler.lookup.FieldBinding.constant(FieldBinding.java:240)
at org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference.getOtherFieldBindings(QualifiedNameReference.java:729)
at org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference.resolveType(QualifiedNameReference.java:1079)
at org.eclipse.jdt.internal.compiler.ast.ReturnStatement.resolve(ReturnStatement.java:341)
at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:641)
at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:309)
at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:551)
at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1188)
at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1301)
at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:590)
at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:861)
at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:141)
at java.lang.Thread.run(Thread.java:744)
Whenever you come across this problem just go to Project > Clean, then select Clean all projects. It should get resolved, otherwise try to delete those jars and add them again.
This means that your project isn't setup to include the JUnit libraries when it compiles; JUnit is not included in the Java runtime libraries (JRE System Library) so you have to add it to the build path.
I suspect the root of your problem is due to the fact that you're trying to use Gradle to tell Eclipse how Eclipse should configure your projects. There is a bit of conflict between Gradle (or Maven) and Eclipse; unfortunately, the Gradle (and Maven) teams have pushed the idea that the build tool is good for generating IDE configurations, when in fact they're not very good at it. The IDE (and developer using it) should be responsible for creating and managing its project configuration files.
Eclipse has Gradle tooling that you can install and knows exactly how to configure and maintain your Eclipse projects correctly based on the build.gradle files in them. It's called Buildship. I strongly recommend you install Buildship and use it to import the projects into your Eclipse workspace. It will properly set up a Classpath Container that stays in sync with the dependencies listed in your build files, as well as properly coordinate the work that Eclipse's compiler needs to do and the work that Gradle itself needs to do so they don't conflict with each other.
It also provides a nice Gradle tasks view that you can use to easily invoke Gradle tasks from within Eclipse (replacing your homemade External Tools configuration).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With