69

When I try to compile this class with javac, I get a compilation error and Test.class is not created.

public class Test {
    public static void main(String[] args) {
        int x = 1L;  // <- this cannot compile
    }
}

But when I create this class in Eclipse, I can see that Test.class appears in target/classes. When I try to run this class from command line with java.exe, I get

Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Type mismatch: cannot convert from long to int

Does Eclipse use its own special Java compiler to create a broken .class? How does java.exe know about complilation problems in .class?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275

3 Answers3

65

This is how the Java compiler knows about the compilation error in the class.

public static void main(String[] paramArrayOfString)
{
    throw new Error("Unresolved compilation problem: \n\tType mismatch: cannot convert from long to int.\n");
}

If you decompile your class file, you can see the above main() method of the class file, which the compiler has generated. This is because of the compiler which Eclipse uses (Eclipse Compiler for Java) is not the same as the standard Java compiler!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rahul
  • 44,383
  • 11
  • 84
  • 103
  • So, it doesn't use `javac`, then can someone compile a .java file in Eclipse after deleting the `javac.exe` file from the JDK kit? Just curious. :) – CᴴᴀZ May 06 '13 at 17:34
  • 5
    @ChaZ - Take a look at this [question](http://stackoverflow.com/questions/3061654/what-is-the-difference-between-javac-and-the-eclipse-compiler?lq=1). Quoting a line from the answer there - `The fact that Eclipse comes with its own compiler is also apparent because you can write, compile, and run Java code in Eclipse without even installing the Java SDK.` Hope that addresses your curiosity!:) – Rahul May 07 '13 at 03:18
42

Eclipse uses the IBM compiler which has an option of creating classes which do not compile, replacing errors with

throw new Error();

IMHO, this is very bad practice and I have seen some very poor quality projects use this. The project didn't compile completely for weeks at a time.

Unlike fail fast strategies, which try to minimise the cost of bugs, discovering bugs as late as possible also maximises the cost of fixing them.

This strategy only works if you are writing prototype code quickly, i.e. code you know will never get into production. (It is hard to be sure this will be the case)

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 13
    Sounds like death call to me. When writing a code, I often try, and I think most people should try, to make the code break at compile time, rather than letting it go as a bug and breaking at production. Now the obvious compile time error is allowed to be veiled, which can be killer/ – mawia May 06 '13 at 07:44
  • 2
    I think in association with all that content assist, auto correction, highlighting, package explorer, ... Eclipse offers you almost can't miss bugs like that. From my point of view it's OK to test classes which don't compile, for instance after you implement an interface, you would have to write several useless returns to tests one single method... I think this would lead to dogged discussion, I just wanted to offer an alternative. – Franz Ebner May 06 '13 at 07:50
  • 1
    @FranzEbner There shouldn't be a chance you will be running code doesn't even compile. ;) IMHO, Mocking code is a better way to handle interfaces in tests. – Peter Lawrey May 06 '13 at 07:53
  • 2
    The advantage of the Eclipse compiler allowing this, is that you can actually run existing code while writing new code (which doesn't compile yet) on your own computer. – Thorbjørn Ravn Andersen May 06 '13 at 08:02
  • @ThorbjørnRavnAndersen The disadvantage is that you start to think this is a good idea when what you want is quality code where you discover bugs as early as possible to minimise the cost of fixing them. – Peter Lawrey May 06 '13 at 09:05
  • 1
    @PeterLawrey I agree that deliberately shipping code that does not compile is a bad thing. Would the "very poor quality projects" you mention have benefittet from introducing a build robot? – Thorbjørn Ravn Andersen May 06 '13 at 09:09
  • @ThorbjørnRavnAndersen indeed, but you shouldn't be checking code which doesn't compile. I don't think it's something to be encouraged. ;) – Peter Lawrey May 06 '13 at 09:15
  • 1
    @Peter: It is sometimes a very useful thing in a fairly big project. You can focus test/debug your piece of code without wasting your time in solving unnecessary problems. – Parvez May 06 '13 at 10:31
  • @Parvez I would fix the real problem which is the quality of the code people are committing. Is having code which compiles setting the bar too high? – Peter Lawrey May 06 '13 at 10:40
  • 1
    @Peter: Fully agree with you and that is the right solution. But unfortunately you don't always have that much control on others. – Parvez May 06 '13 at 11:21
  • Which leads to an interesting question: is there a quick way to scan evey jar on the classpath to see if any of their classes has such compilation problems? – Haroldo_OK Apr 14 '14 at 14:14
  • @Haroldo_OK You could do this but it is much better to have your compiler tell you this at compile time. – Peter Lawrey Apr 14 '14 at 20:50
  • @PeterLawrey The compiler is already telling me this; the problem is that not every developer takes the time to notice such details; of course, it would be possible to cleanup and rebuild everything to automatically check this, but I suppose scanning the classpath for classes with unresolved compilation problems would be a very good (and fast) first step, so that incomplete builds could be rejected right away. – Haroldo_OK Apr 15 '14 at 12:57
  • @Haroldo_OK If a developer ignores compilation error as a "detail" why would they bother going back and looking for compilation errors they should have picked up the first time. I just wouldn't allow you to run/deploy code which doesn't compile. – Peter Lawrey Apr 16 '14 at 07:52
  • @PeterLawrey That's exactly what I'm thinking about: automating this process, so that sources with compilation errors would be automatically prevented from being deployed. I know it could be done by simply rebuilding everything but, in our case, checking it that would take a few minutes, so it would be better to have a quick check first, that would reject the developer's code right away if it's not fully compiled, and let the continuous integration server take care of the longer test. – Haroldo_OK Apr 16 '14 at 14:47
  • @Haroldo_OK I really see this as a training issue. You should ensure this isn't happening in the first place. – Peter Lawrey Apr 16 '14 at 14:53
  • @Haroldo_OK And I suggest you use something like maven and continuous integration and not be passing around JARs someone built on a PC somewhere. – Peter Lawrey Apr 16 '14 at 15:31
  • 1
    So how do we disable this IBM compiler option in Eclipse? – pacoverflow Jun 19 '14 at 06:59
27

Yes, Eclipse uses its own special compiler; known as "ecj". From Stack Overflow question What is the difference between javac and the Eclipse compiler?:

One notable difference is that the Eclipse compiler lets you run code that didn't actually properly compile. If the block of code with the error is never ran, your program will run fine. Otherwise it will throw an exception indicating that you tried to run code that doesn't compile.

Community
  • 1
  • 1
Erich Schubert
  • 8,575
  • 2
  • 26
  • 42