Ant builds differently from Eclipse - java

How come Eclipse compiles my project (automatically) without errors, but when I run Ant build.xml -> compile target, the build fails with compile error:
<MyClass> is not abstract and does not override abstract method <someMethod>
I understand this error message, but it seems not to be true, because 1) Eclipse shows no errors 2) Deploying this project to server succeeds and the class works as it should work.
So how is this problem even possible?

Are you using some special extensions to Eclipse, like Lombok (could be the extension generate something for you)?
Are you using some special framework (could be the framework generate some class for you)?
What you also need to understand is Eclipse and Ant using different compiler. Eclipse has its own compiler which behave differently with the Sun JDK, or with certain version of Sun JDK. One example of such behavior can be read here. But before I jump to that conclusion, I will inspect all configurations I have on my Eclipse.

It's also possible that your Ant build is just not set up the same as your Eclipse build. Different source folders, different JARs, etc. For example, perhaps your Eclipse build references an old version of a third-party JAR, and your Ant build references a new version where a new abstract method was added to a class you're inheriting from.

Because there are minor differences in the Eclipse compiler. I found a bug once, too, where the Javac threw an (IMHO stupid) error, while the Eclipse compiler was able to compile it like expected.
FYI: Eclipse uses a different compiler (its own) because it needs one optimized for incremental builds while you type.
Create a test case that shows that the differences are real, and send it to the eclipse team. They will adjust the behaviour of their compiler. However, I can't believe that such a major bug like an unimplemented method is really in the Eclipse compiler. I therefore assume you find the bug in your setup while creating a testcase for that.

Thank you all for your quick answers. It has been very helpful to understand that Eclipse uses different compiler, that explained a lot.
As for my problem - I assumed that Java compiler is right and that the build actually had errors. On closer examination, it occured to be the incompatibility of an older version of Apache Commons DBCP with Java 1.6. I was sure I was using the latest one and consulted wrong documentation version, which stated that the required methods were implemented.
Now as for Eclipse. The bug is actually tricky. I managed to write a test case showing this bug. I use Java 1.6 and Eclipse Helios for Java EE. I created a Java project in Eclipse and added
com.springsource.org.apache.commons.pool-1.5.3.jar
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
to the classpath (downloaded these JARs from SpringSource repository). As you see, Apache Commons DBCP is an old one. Java 1.6 requres version 1.4+.
In my test project I extend org.apache.commons.dbcp.BasicDataSource and additionally said it should implement javax.sql.DataSource. Like this:
import org.apache.commons.dbcp.BasicDataSource;
import javax.sql.DataSource;
public class MyDataSource extends BasicDataSource implements DataSource {
}
The tricky part here is that BasicDataSource implements DataSource interface. But in version 1.6 this interface got extended it, so the new methods are not implemented. Adding "implements DataSource" again explicitly should cause and error, which Java compiler successfully reports. But Eclipse compiles this code without any warning and it even runs.
So that was the problem. Seems like a bug in Eclipse to me.

Related

Java 8 - Can not import java.util.Arrays [duplicate]

I just encountered a strange error when switching the JDK version of a new Project of mine from 7u45 to 8u20. A harmless LogManager declaration at the beginning of my class is being refused with the following error:
The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
This is the code:
public class Class1 {
private static Logger log = LogManager.getLogger(Class1.class);
...
Eclipse proposes me to configure the build path, but I have no Idea what to configure because I don't know the underlying problem of that error.
Using the JDK with version 7, everything works fine.
When using JDK 8 and an IDE (or any other code processing tool/framework) with its own compiler, like Eclipse, you have to update the tool to a version with Java 8 support, even if you are not using the newer Java 8 features.
The reason is that the compiler must be able to load the newer class files of the JRE in order to compile your software which references these classes.
Sometimes you can get away with an older compiler when it ignores the newer version number of the class files. But some types will confuse older class file parsers as they use new features, notably AnnotatedElement, which now has default methods, and Map.Entry, an interface which now has static methods.
It seems that Eclipse does not make a difference between references for which no class file could be found and class files it failed to read when saying “«classname» cannot be resolved”.
The same applies to all tools and frameworks using ECJ as embedded compiler.
If this happens to you in Tomcat running from within Eclipse (question was closed as duplicate and redirects here), go to Preferences → Server → Runtime Environments → Tomcat version → Edit… and make sure the selected JRE matches the Tomcat version. (Maybe you need to install one.)
Solution 1:
Try changing the source level.
Go to Project > Preferences > Java Compiler.
Enable Project specific settings
Set compiler compliance level to 1.4 or below.
Restart
Solution 2:
Create a new workspace.
Copy project files into the new workspace.
Import project into eclipse and rebuild.
I change from JRE 8 to JRE 7 and restart Eclipse then it works fine.
I was using Eclipse Helios with JRE 8 and updating the software solve the problem.
Now I'm using Eclipse Mars and works just fine -> https://eclipse.org/downloads/

Java Compilation Errors: Unsupported Class Version

I recently finished a project in Eclipse and it ran without a problem. Then recently I imported a new assignment to work on for class, but when I did my old project all of a sudden had a x on its icon. I looked through the code, nothing had been changed, but it threw this error in the console:
java.lang.UnsupportedClassVersionError
at java.lang.ClassLoader.defineClass1(Native Method)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.loadClass(RemoteTestRunner.java:685)
And others. Is this possibly due to the version of java being used or something else?
An UnsupportedClassVersionError is thrown when you use a higher JDK version to compile than when you try to run the program. For example, you compile Program.java using JDK1.7 but then attempt to run using JDK1.6. I am guessing that upon importing the new assignment for your class, you unknowingly adopted to use the JDK that the imported project was compiled in.
I suggest going to Eclipse Preferences and taking a look at your installed JRE's to make sure everything is okay and also to look at the projects Properties and looking at its Build Path. In general, make you you are using a version to run in that is at LEAST what you used to compile it. If you chose a higher version everything will still be okay.
EDIT:
Here is a link for more information on the matter and where I had originally read about this. I knew I had saved the link somewhere.
http://javarevisited.blogspot.com/2011/07/javalangunsupportedclassversionerror.html

Error when using LogManager (l4j2) with Java 8 (java.lang.reflect.AnnotatedElement cannot be resolved)

I just encountered a strange error when switching the JDK version of a new Project of mine from 7u45 to 8u20. A harmless LogManager declaration at the beginning of my class is being refused with the following error:
The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
This is the code:
public class Class1 {
private static Logger log = LogManager.getLogger(Class1.class);
...
Eclipse proposes me to configure the build path, but I have no Idea what to configure because I don't know the underlying problem of that error.
Using the JDK with version 7, everything works fine.
When using JDK 8 and an IDE (or any other code processing tool/framework) with its own compiler, like Eclipse, you have to update the tool to a version with Java 8 support, even if you are not using the newer Java 8 features.
The reason is that the compiler must be able to load the newer class files of the JRE in order to compile your software which references these classes.
Sometimes you can get away with an older compiler when it ignores the newer version number of the class files. But some types will confuse older class file parsers as they use new features, notably AnnotatedElement, which now has default methods, and Map.Entry, an interface which now has static methods.
It seems that Eclipse does not make a difference between references for which no class file could be found and class files it failed to read when saying “«classname» cannot be resolved”.
The same applies to all tools and frameworks using ECJ as embedded compiler.
If this happens to you in Tomcat running from within Eclipse (question was closed as duplicate and redirects here), go to Preferences → Server → Runtime Environments → Tomcat version → Edit… and make sure the selected JRE matches the Tomcat version. (Maybe you need to install one.)
Solution 1:
Try changing the source level.
Go to Project > Preferences > Java Compiler.
Enable Project specific settings
Set compiler compliance level to 1.4 or below.
Restart
Solution 2:
Create a new workspace.
Copy project files into the new workspace.
Import project into eclipse and rebuild.
I change from JRE 8 to JRE 7 and restart Eclipse then it works fine.
I was using Eclipse Helios with JRE 8 and updating the software solve the problem.
Now I'm using Eclipse Mars and works just fine -> https://eclipse.org/downloads/

Java compilation with two versions of Eclipse

I've got an old project in Eclipse 2.1 and compiled with a JDK 1.4.2_12. I want to upgrade the version of Eclipse to Eclipse Galileo.
I've imported my project and set the compilation level to 1.4 and I've also updated my build path to use the correct JDK.
The problem is that when I compare the compiled files in the classes folder in the two versions of Eclipse, the MD5 checksum are different.
Should I be worried about that fact or this is normal?
This is normal. The Eclipse compiler is free to change the class file structure as long as it conforms to the 1.4 JVM specification. If a 1.4 JVM will load and run the class, I see no issue.
For truly pedantic cases, you should do your final builds with a JDK which matches the JRE, and not the Eclipse compiler.
As long as the program is working i dont think that you need to worry!!!
As MD5 would be unique for each entity, and it represents the Hash value.
It's normal, but I would make sure about doing a complete rebuild anyway (possibly erasing any existing class files). My experience with Eclipse is that the incremental builder doesn't react well to unexpected situations.

Java : Is there a tool to make code (in a 3rd party JAR) forward compatible (1.4 - 1.6)

I have a 3rd party JAR file that is compiled using Java 1.4. Is there a tool that can make the jar file compatible with Java 1.6? (Something like 'retrotranslator' but what does the reverse of it).
I tried decompiling the class files and re compile them in 1.6 but it fails.
Here is the issue:
My project uses 'rsadapter.jar' for was 5.1 and I had my project setup in Eclipse 2.0 + JDK 1.4 and it used to work fine. Now, I have migrated to Java 1.6 and Eclipse Ganymede (as per the requirements) and the same project (exactly same setup) started complaining about the missing class files in the 'rsadapter.jar'. I put the JAR in classpath explicitly too but it still could not load the classes. Then I changed the Java Compiler version to 1.4 and it started working.
Regards,
- Ashish
Classes compiled by JDK 1.4 should be usable in a Java 6 runtime as-is. If you have actually encountered a problem, please describe it.
Update: I can only reproduce this with types in the "default" package (that is, not in a package). Are the classes you are trying to use in the default package? Also, this happens to me regardless of the JDK version used to compile.
Update: Okay, after a little research, I realized that you can never reference a type in the unnamed package from a named package. Makes sense, but definitely not what you are running into.
I can compile code under JDK 1.4.2_19 and utilize it just fine in a Java 6 Eclipse project. I think that this problem is something specific to your environment. In this situation, I would backup Eclipse and recreate everything (JDK installation, workspace, projects) from scratch, to see if I could clear it up.
I had another issue with some legacy code written in Java 1.4.x: the authors loved enumerations and loved to name the corresponding variables 'enum'. They even used it for package names. And this prevents from compiling the code under Java 1.5 (or higher) quite successfully.
Changing that automatically is quite an issue.
May be you have defined Eclipse to throw compiler errors on use of deprecated methods or classes?

Categories

Resources