Community
Participate
Working Groups
BETA_JAVA8: If a 1.7- project that builds fine against a 1.7 JRE is compiled against 1.8 JRE, the code may not compile anymore. This can happen for instance when the 1.8 JRE introduces a brand new method in an existing interface and provides a default implementation for that. We need to consider how best to support (or not) this scenario, the cost benefit analysis etc. Stephan, could you identify the problem scenarios and provide small snippets for them based on how you tweaked our test suites to address the problems encountered there. See that javac7 will refuse JRE8 class files. javac8 when invoked with -source 1.7 option skips the interface method bodies and treats them as plain abstract methods.
I'm using the following aliases for various compiler invocations: javac7: oracle javac 1.7 with default options javac8: lambda enabled javac with default options javac8-7: lambda enabled javac with -source 1.7 -target 1.8 ecj7: ecj as of Juno GA with option -1.7 ecjb8: ecj from BETA_JAVA8 with option -1.8 ecjb7: ecj from BETA_JAVA8 with option -1.7 ------------------------------------------------------------------------- 1. Experiment: Compile with javac8 or ecjb8 (equal bytes): package pack; public interface I { void foo() default {} } Then consuming the above from its .class file compile this: package pack; import pack.I; public class CI implements I {} Results: javac7: silent javac8: silent javac8-7: 1 warning: warning: [options] bootstrap class path not set in conjunction with -source 1.7 ecj7: silent ecjb8: silent ecjb7: 1 error: The type CI must implement the inherited abstract method I.foo() ================================ Discussion: javac7 being silent is UNEXPECTED, does it see that foo is non-abstract? javac8-7 being silent is even more UNEXPECTED. ecj7 results are basically expected since we changed only recently how non-abstract interface methods are interpreted. ================================ ------------------------------------------------------------------------- 2. Experiment: Compile this class: package pack; import java.util.Collection; import java.util.Iterator; public class CCollection implements Collection<String> { public int size() { return 0; } public boolean isEmpty() { return false; } public boolean contains(Object o) { return false; } public Iterator<String> iterator() { return null; } public Object[] toArray() { return null; } public <T> T[] toArray(T[] a) { return null; } public boolean add(String e) { return false; } public boolean remove(Object o) { return false; } public boolean containsAll(Collection<?> c) { return false; } public boolean addAll(Collection<? extends String> c) { return false; } public boolean removeAll(Collection<?> c) { return false; } public boolean retainAll(Collection<?> c) { return false; } public void clear() {} } Results: javac7: silent javac8: silent javac8-7: 1 error, 1 warning: warning: [options] bootstrap class path not set in conjunction with -source 1.7 CCollection is not abstract and does not override abstract method addAll(Iterable<? extends String>) in Fillable Using -bootclasspath pointing to the lambda enabled JRE: javac7: 1 error: CCollection is not abstract and does not override abstract method addAll(Iterable<? extends String>) in Fillable ecj: all variants are silent when run on JVM 7 Running ecj on the lambda enabled JVM: ecj7: silent ecjb8: silent ecjb7: 26 errors, all like The type CCollection must implement the inherited abstract method Collection<String>.addAll(Iterable<? extends String>) ================================ Discussion: javac results are expected, since fillAll(Iterable) is a default method. The surprise is in the difference to experiment 1. ecj on JVM 7 is expected, the default methods are not present here. ecj on lambda enabled JVM 8 results are basically expected since we changed only recently how non-abstract interface methods are interpreted. ================================ ------------------------------------------------------------------------- 3. Experiment: Let our compiler produce class file with version 52 (javac still produces 51). Consume the 52 version class file: all variants of javac: 1 warning major version 52 is newer than 51, the highest major version supported by this compiler. It is recommended that the compiler be upgraded. all variants of ecj: silent ------------------------------------------------------------------------- Results: I have no explanation why javac7 and javac8-7 are silent in Experiment 1. The only difference between the interfaces I and Collection that comes to mind is: one is part of the JRE while the other one is my own. Having a deep look into the byte code I could not find a significant difference. No default method is marked with a special modifier or such. As long as javac doesn't make up its mind how to interpret default methods below 1.8 I don't believe we can successfully mimic its behavior. Shouldn't ecj start emitting warnings regarding unsupported class file versions?
(In reply to comment #0) > Stephan, could you identify the problem scenarios and provide small > snippets for them based on how you tweaked our test suites to address > the problems encountered there. The tweaks I applied to the test suite basically go like this: Check the system property "java.specification.version" of the running vm for "1.8". If found, add stub implementation for all relevant new interface methods (with default body) to all implementing test classes. The bulk of http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=dd3bff4d99a5193497eb7e3c0e1bc46a32b7c36a is only devoted to this tweak (incl. string based substitution of type parameters). This way our tests work fine, but in modes below the host VM version we're basically operating in the very situation that is considered as "unsupported".
(In reply to comment #0) > See that javac7 will refuse JRE8 class files. It *will* eventually emit a _warning_. Currently, there are no class files recognizable as Java8. > javac8 when invoked with -source 1.7 option skips the interface method > bodies and treats them as plain abstract methods. Sometimes, but not in Experiment 1 above.
I see these possible action items: A. wait until class file version 52 is in use by all tools B. ask oracle about the difference between Experiments 1 & 2 C. add a warning re incompatible class file version to ecj. D. wait until the access bit for default methods shows up. E. work with releng to provide multiple JREs into the test suite and always compile against the one matching the compliance level.
(In reply to comment #4) > A. wait until class file version 52 is in use by all tools OK, lambda enabled jdk b74 uses class file version 52. Re-testing with this jdk yields: In Experiment 1 javac8-7 remains silent (except for the general warning re bootstrap class path). This is EVEN MORE UNEXPECTED (I used a version 52 pack/I.class) and javac8-7 should report that we're facing something in I which we can't support at -source 1.7. To add insult to injury: javac8-7 (i.e., compiling with -source 1.7) creates a class file with version 52, too! So even when compiling for 1.7 running on a 1.7 VM yields: java.lang.UnsupportedClassVersionError: pack/CI : Unsupported major.minor version 52.0 Conclusion: javac is not yet in a state where we should copy any behavior in these regards.
Let's give an entirely new twist to this story: Recall: in October I spoke to Oracle people how to handle this compatibility issue, and they made me feel the question itself is wrong: no help should ever be given to users for compiling in 1.7 mode against a 1.8 JRE (my words, not exactly theirs). As a result we implemented (in bug 388954) that the body of default methods found in class files should simply be ignored and AccAbstract silently added instead. This required significant rework across the entire test suite (bug 388800). From doing more experiments I learned that even in 1.7 mode javac8 uses some sophistication for gracefully dealing with default methods: - clients of the interface can see the default method as a normal interface method, ready to be called. - implementors of the interface *do not* see the default method at all, as demonstrated by two facts: - implementors do *not* have to implement any default methods from the super interface - implementors can *not* resolve the inherited method in any self calls! This behavior was actually already present at least in b47, just nobody explained their strategy. Here's the snippet that reveals the strategy: // compile separately first: public interface I { default void foo() {} } // then compile this consuming the above from .class: public class CI implements I { void test(I i) { this.foo(); i.foo(); } } javac8 -source 1.7 -target 1.7 answers a single error: pack/CI.java:5: error: cannot find symbol this.foo(); ^ symbol: method foo() So, "this" (instanceof CI which implements I) knows no method "foo", whereas "i" of type "I" does. Do we want to mimic this behavior? Looks kind of crude to me, but, OTOH, it might indeed avoid some of the issues I was raising in the first place. Let me reveal one more mystery: why did javac8-7 produce in experiment 2 the following message (older versions only): CCollection is not abstract and does not override abstract method addAll(Iterable<? extends String>) in Fillable ? Because: - in early versions (e.g., b50) Collection extended an interface Fillable with a *regular* (i.e., abstract) interface method addAll(). - Collection had (and still has) a default method of the same signature - for javac8 the default method implemented the inherited abstract method - when analyzing the inheritance structure, javac8-7 *only* saw the abstract method in Fillable, but *not* the implementation in Collection. Ergo, using a default method to implement an inherited abstract method is an anti pattern, should this occur in any library, cross-compilation will break. Implementationwise, in order to mimic this behavior we should probably mark default methods, which we find while in 1.7 mode as (AccAbstract|AccDefaultMethod). Only so, can we - treat them as normal abstract methods in call scenarii - simply drop them when analyzing inheritance Which also means: we can *not* rely on isDefaultMethod() indicating that we are compiling for Java8, which we are currently doing in several locations.
From answers on the EG list I conclude: - the observed behaviour of javac8 is more a result of its implementation than a carefully designed solution. The fact that inherited default methods cannot be called via the class simply results from javac's strategy to never search in interfaces when a method is invoked an a non-abstract class. By contrast ecj avoids to report such errors, which we consider to be uninteresting secondary errors (the primary error being an unimplemented method). What ever happens to be the straight forward behaviour in javac, may not even be easy to achieve in ecj. - that behaviour of javac may well change in the future - it's too early to make a call now, javac developers have more important tasks on their plates now. This bug is in state IDLE now.
News from the EG list: http://mail.openjdk.java.net/pipermail/lambda-spec-experts/2013-November/000437.html The essence: "javac does a lot of work to ensure that, under -source 7, default methods are "visible" at appropriate times, but don't get in the way:" It seems we should make ecj -1.7 aware of default methods to some extent, too.
*** Bug 426789 has been marked as a duplicate of this bug. ***
reclassifying this to be CR rather than ER - I think users will find this to be a bug rather than an enhancement. JDT/Debug could be a verification target when this is completed. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=426789
(In reply to Srikanth Sankaran from comment #10) > reclassifying this to be CR rather than ER - I think users will find this to > be a bug rather than an enhancement. Point taken. From a user's p.o.v. I totally agree. A bug as in "a deviation from the specified behaviour" I must object: this behaviour is explicitly unspecified :) > JDT/Debug could be a verification target when this is completed. See > https://bugs.eclipse.org/bugs/show_bug.cgi?id=426789 Good point. I'll try to attend to this soon. I guess the most straight-forward approach will be to let the compiler at compliance 1.7 exactly *understand* what a default method in a class file is, and perform (a slight variant of?) 1.8 validation actually.
Dani and Markus, Unless I hear strong objections, I would like to move this task out of Java 8 GA to 4.4 (or perhaps 4.5). This is completely out of the realms of specification and involves risky changes. Parts of the compiler should get default methods exposed to them and other not. We don't have a precise picture of the contours of the solution. While in the long run, "best case" efforts should be made to support this scenario, compatibility here is against javac which is an opaque/ black box for us. FWIW, see that the equivalent scenario of inter-operability of 1.4 programs'with 1.5+ projects/libraries was not solved till 2012 Dec many years after 1.5 support shipped. https://bugs.eclipse.org/bugs/buglist.cgi?classification=Eclipse&component=Core&list_id=8172697&product=JDT&query_format=advanced&short_desc=1.4%2F1.5&short_desc_type=allwordssubstr Please share your opinion either way.
(In reply to Srikanth Sankaran from comment #12) > FWIW, see that the equivalent scenario of inter-operability of 1.4 > programs'with 1.5+ projects/libraries was not solved till 2012 Dec many > years after 1.5 support > shipped. I meant till Dec 2010.
I agree with taking this out of the Java 8 GA bucket, but I think we should aim to address frequently-encountered problems for 4.4. I.e. the goal should be to allow basic development of 1.6/1.7 projects in situations where only a Java 8 JRE is available. Good test case: Compile Eclipse SDK projects from source with only a Java 8 JRE. I'm not sure about the 1.4/1.5 bugs you cited. Was the interoperability really unusable before those fixes? Or was this just the last batch of fixes for corner cases?
E.g. these classes should compile: import java.util.Comparator; public class MyComp implements Comparator { @Override public int compare(Object o1, Object o2) { return 0; } } class MyStringComp implements Comparator<String> { @Override public int compare(String o1, String o2) { return 0; } } In BETA_JAVA8 you get 7 compile errors "Type must implement the inherited abstract method Comparator.reversed()", etc.
(In reply to Markus Keller from comment #14) Thanks for weighing in. > I'm not sure about the 1.4/1.5 bugs you cited. Was the interoperability > really unusable before those fixes? Or was this just the last batch of fixes > for corner cases? I don't think they were corner cases. They were blockers in that code would not compile and fail with name clash errors and iirc runtime failures due to missing bridges and such. I don't know that it was unusable before this cluster of bugs was fixed - what we do know that as soon as some of the eclipse projects entered into this mode (IIRC Equinox) they were hit with this and there were a series of 10-12 problems that needed to be attended to.
(In reply to Markus Keller from comment #15) > E.g. these classes should compile: So, ecj -1.7 must understand default methods, I don't see a way around that, because the same method must behave like an interface method (for clients) and like a concrete method (for implementors). In particular for the implementors view the following options *don't* work: - treat the method as a regular interface method: would force implementors to implement it. - make the method invisible: the default method could be migrated from a regular interface method. Implementors must be able to call it in self calls. I'll give it a quick shot and let you test it and decide into which bucket it should go :)
*** Bug 426265 has been marked as a duplicate of this bug. ***
Just chipping in that I've hit this problem in a project of mine this week. The codebase is primarily for use on 1.6 so is compiled with 1.6 compliance. A couple of classes (that only get loaded when we're on 1.8) are interacting with 1.8 classes (LambdaMetaFactory). Because I can't compile with compliance 1.6 against a 1.8 JRE (I get all the problems with default methods being reported) I'm going to have to do some nasty rework to split my project into 1.6 and 1.8 pieces ... no fun. Am I right in thinking there were versions of ECJ BETA_JAVA8 where this worked? So my alternative is to go back to one of those ... nasty.
(In reply to Andrew Clement from comment #19) > Just chipping in that I've hit this problem in a project of mine this week. > The codebase is primarily for use on 1.6 so is compiled with 1.6 compliance. > A couple of classes (that only get loaded when we're on 1.8) are interacting > with 1.8 classes (LambdaMetaFactory). Because I can't compile with > compliance 1.6 against a 1.8 JRE (I get all the problems with default > methods being reported) Just a quick idea: if it's a small number of classes from JRE 8 you are referencing: couldn't you compile against JRE 6 + selective jars from JRE 8, configured such that JRE 8 is used only as a fallback for classes missing in JRE 6? > I'm going to have to do some nasty rework to split > my project into 1.6 and 1.8 pieces ... no fun. That would probably be the orthodox solution ;-P A main module that compiles and runs against JRE 6 plus an optional fragment that adds more capabilities, if enabled. You're probably aware of the dangers that any API calls could cause linking errors at runtime, when compiling against JRE 8 and running on JRE 6. These dangers would be reduced by the main + fragment approach :) > Am I right in thinking there were versions of ECJ BETA_JAVA8 where this > worked? So my alternative is to go back to one of those ... nasty. I can't recall such version, sorry.
The bug fix I was thinking of that was dealt with previously was: https://bugs.eclipse.org/409473 "JDT cannot compile against JRE 1.8" I think I was considering that also covering default methods in some way, guess not. Yes I can mess around with my project configuration but basically as it stands: - my code builds fine with javac, my gradle build is perfectly happy, my build system is perfectly happy - but I can't use eclipse to work on my codebase... (my code is like Markus' comment #15)
(In reply to comment #21) > Yes I can mess around with my project configuration but basically as it stands: > - my code builds fine with javac, my gradle build is perfectly happy, my build > system is perfectly happy > - but I can't use eclipse to work on my codebase... > > (my code is like Markus' comment #15) Could the patch from Attachment 240135 [details] on bug 428203 be useful here? Provided as a checkbox option somewhere, perhaps?
*** Bug 430793 has been marked as a duplicate of this bug. ***
shouldn't this have a higher priority ? one of the forces of Eclipse JDT have always been that it supports crosscompilation.
Yes, we should try to improve this for Luna M7. Although it's technically wrong to compile against a JRE that has a higher version than the source level, we know that many users are willing to accept some problems this can entail (but not the current complete blockage). (In reply to Stephan Herrmann from comment #17) > So, ecj -1.7 must understand default methods, I don't see a way around that, > because the same method must behave like an interface method (for clients) > and like a concrete method (for implementors). Yes. Stephan, can you take this up for M7? If not, please assign to someone else.
> (In reply to Stephan Herrmann from comment #17) > > So, ecj -1.7 must understand default methods, I don't see a way around that, > > because the same method must behave like an interface method (for clients) > > and like a concrete method (for implementors). > > Yes. Stephan, can you take this up for M7? If not, please assign to someone > else. I'll try to find some time within 2 weeks from now.
(In reply to Srikanth Sankaran from comment #16) > I don't know that it was unusable before this cluster of bugs was fixed - > what > we do know that as soon as some of the eclipse projects entered into this > mode > (IIRC Equinox) they were hit with this and there were a series of 10-12 > problems > that needed to be attended to. Srikanth is correct. Equinox had issues when attempting to compile against Java 5 class libraries but using the jsr14 compile flag. Our motivation for using that setup was so that we could use the generic APIs (e.g. Map<?,?>) from java SE 5 in our code while still being able to produce classes that could run on java 4. I remember that it was a non-trivial task for ecj to continue to support that setup. This is also a setup that I no longer use BTW. This is because as of javac7 the jsr14 compiler option is no longer supported. OSGi felt it as no longer reasonable to continue to ship jsr14 compiled class files. As such Equionox no longer supports Java SE 4 based VMs (i.e. Java ME) That in itself was a sort of corner case (although important to OSGi since we still wanted to support Java ME). Now moving up to Java 8. I'm not sure I see a great usecase for compiling against Java 8 class libraries while targeting < Java 8.
(In reply to Thomas Watson from comment #27) > (In reply to Srikanth Sankaran from comment #16) > Srikanth is correct. Equinox had issues when attempting to compile against > Java 5 class libraries but using the jsr14 compile flag. OK, I agree the unofficial jsr14 flag had problems, but that's not the equivalent of this bug. I think we behaved reasonably well if you just used compliance 1.4 and an rt.jar from 1.5. That's the situation users run into when they check out a 1.5/1.6/1.7 project and just want to get something running.
(In reply to Markus Keller from comment #28) > I think we behaved reasonably well if you just used compliance 1.4 and an > rt.jar from 1.5. That's the situation users run into when they check out a > 1.5/1.6/1.7 project and just want to get something running. The following has no bearing on the priority with which this bug should be fixed, but it is worth pointing out that until the cluster of bugs fixed in the context of jsr14 were fixed, the compiler was not even internalizing the type parameters of a class from 1.5+ binaries/projects if project compliance was 1.4-. That would mean many things could not have behaved reasonably well for a certain cross section of applications (basically those that subtype a 1.5+ generic class) while for applications that merely used the 1.5 classes things would have worked fine since erasure guarantees that.
I was hit by this too, I was using java-8-oracle to compile for
(In reply to Missing name from comment #30) > I was hit by this too, I was using java-8-oracle to compile for I have it on my agenda for M7, but still I'm puzzled why so many people insist in using this broken/incorrect/unsupported configuration.
(In reply to Stephan Herrmann from comment #31) > I'm puzzled why so many people insist in using this broken/incorrect/unsupported configuration. Each of my projects needs to target the environment running on it's server until that gets upgraded, and having a bunch of JDK's installed on my workstation is a PITA. And, due to the presence of options for 'source' and 'target' versions in the compiler, there is an expectation of being able to use a newer JDK to build code targeting an older environment, else, why have those options at all?
(In reply to Chris Hubick from comment #32) > (In reply to Stephan Herrmann from comment #31) > > I'm puzzled why so many people insist in using this broken/incorrect/unsupported configuration. > > Each of my projects needs to target the environment running on it's server > until that gets upgraded, and having a bunch of JDK's installed on my > workstation is a PITA. I don't know what should be particularly painful about that. :) If you are professionally developing projects targeting different JREs you *should* have each of these installed (JRE suffices, no need to have the full JDK). How else do you ensure you are not using API that doesn't even exist in your target environment? > And, due to the presence of options for 'source' and > 'target' versions in the compiler, there is an expectation of being able to > use a newer JDK to build code targeting an older environment, else, why have > those options at all? So that's what raises the expectation? But wait: that dialog doesn't even allow you to enter any of the bogus combinations of source/target/compliance levels. Mh...
(In reply to Stephan Herrmann from comment #33) > How else do you ensure you are not using API that doesn't even > exist in your target environment? The existing projects are normally just in maintenance mode with minimal such changes. Or my brain remembers what is new API. Or the Javadoc tells me. Or the build server goes red :) And if I'm going to make significant changes to a project, I'll likely then also upgrade it to current JDK at that time. > > And, due to the presence of options for 'source' and > > 'target' versions in the compiler, there is an expectation of being able to > > use a newer JDK to build code targeting an older environment, else, why have > > those options at all? > > So that's what raises the expectation? But wait: that dialog doesn't even > allow you to enter any of the bogus combinations of source/target/compliance > levels. Mh... Everything I do is Maven/m2e, so I'm not really twiddling any dialogs. Most existing projects have source/target 1.7/1.7 in their pom.xml, untouched from before I upgraded to 1.8. When I upgrade my workstation JDK to 1.8, and Eclipse to a 1.8 version, in an ideal world, I could just start up Eclipse and create a new 1.8 project (which I can), but all my old 1.7 projects would continue to build and display "green", just as they did before. But, oh no, forget that, thanks to this bug, everything that used to be happy then exploded in a sea of red errors after I upgraded. Previous upgrades resulted in little things like use of "enum" keywords, and maybe warnings for things like missing type parameters on collections. You could easily fix those errors or ignore/remove those warnings. But this, this is more of a show-stopper "it won't even build" scenario, with no easy workaround. So, yeah, because of this bug, I had to go back and reinstall a 1.7 JDK on my system. As a matter of good stewardship, when a new JDK is released, I like to at least grab it and immediately make whatever little fixes might be required on my projects to ensure they are at least buildable/runnable using that newer JDK, even if they are still primarily targeting the old one. After having done that, it also just *feels* messy still needing the old one installed myself.
(In reply to Chris Hubick from comment #34) > But, oh no, forget that, thanks > to this bug, everything that used to be happy then exploded in a sea of red > errors after I upgraded. The reason for the errors you see is not in eclipse but because you removed the JRE 7 which *is* necessary to do 1.7 development in a controlled way. None of what you are saying improves my motivation to invest my spare time for this bug.
(In reply to Stephan Herrmann from comment #35) > The reason for the errors you see is not in eclipse but because you removed > the JRE 7 which *is* necessary to do 1.7 development in a controlled way. Then I'm back to not understanding why there are "source" and "target" options anywhere. > None of what you are saying improves my motivation to invest my spare time > for this bug. I just CC'd to find out if I might be able to remove 1.7 before I'm done upgrading all my projects, and thought I might be able to respond to your query by communicating that some of us are used to being able to upgrade our JDK and have all our old projects still build without modifications. Frankly, "suck it up" is a perfectly valid answer, as I don't think I'd invest *my* spare time in fixing this either ;)
This is such a pain when working with Eclipse plugins. Where am I going to find a CDC-1.1/Foundation-1.1 JRE?
(In reply to Timo Kinnunen from comment #37) > This is such a pain when working with Eclipse plugins. Where am I going to > find a CDC-1.1/Foundation-1.1 JRE? Does bug 386649 have what you need? Does installing "API Tools Execution Environment Descriptions" help?
(In reply to Timo Kinnunen from comment #37) > This is such a pain when working with Eclipse plugins. Where am I going to > find a CDC-1.1/Foundation-1.1 JRE? Wait a minute: this bug is about mixing 1.7 with 1.8. Why would you need a CDC-1.1/Foundation-1.1 JRE?
(In reply to Stephan Herrmann from comment #39) > Wait a minute: this bug is about mixing 1.7 with 1.8. Why would you need a > CDC-1.1/Foundation-1.1 JRE? This bug is actually about compiling pre-1.8 projects against a 1.8 JRE. E.g. org.eclipse.core.jobs is still at CDC-1.1/Foundation-1.1 and should also compile with a Java 8 JRE.
Given we are not bound by any specification in this issue, a solution is actually simple, as mentioned before: remove one check for sourceLevel >= JDK_1_8 and let the compiler at 1.7- handle binary default methods just like a 1.8 compiler would. I only found one more error message which should be suppressed at 1.7- (duplicate default methods). In comparison with javac I only see one difference: we are *not* copying the weird behavior discussed in comment 6 (which as I understand is an artifact of their implementation strategy for method lookup). I could also compile all JDT/Debug sources against JRE8. Released for 4.4 M7 via http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=8477130b01f048bfc1fd1f484a88902aeefb2f38 Please test whether this is what people are expecting. In particular we might accept programs that can produce problems at runtime (unimplemented method, or method not found), but since we are explicitly disabling strict compatibility checks, we cannot perform some strict compatibility checks :) IOW: when using this setup, users have to know exactly what they are doing! IOW: my recommendation to avoid this setup if humanly possible still holds. Final question: do we want to add a warning when reading a class file with higher version than the current target? Might just be a question of where exactly to report (don't want to have myriads of duplicate warnings, but still want a hint at were it occurred).
See also bug 431911.
Looks promising so far, thanks! Although I'm hesitant to unravel my 1.2-1.5 JRE workarounds just yet at least a quick try on a CDC-1.1/Foundation-1.1 project has it building without errors. As long as it's possible to run it on a 1.8 JRE successfully that's good enough. Not that I plan on doing that, the priority has always been a Challenges view free of compile errors.
> IOW: when using this setup, users have to know exactly what they are doing! > IOW: my recommendation to avoid this setup if humanly possible still holds. Yeah, I think that's always been our advice ... and you can see how well people follow it :) > Final question: do we want to add a warning when reading a class file with > higher version than the current target? Might just be a question of where > exactly to report (don't want to have myriads of duplicate warnings, but > still want a hint at were it occurred). I don't think we currently do, do we? But seems like a good idea ... maybe "once per project" (if "you" have knowledge of project, or else package?, and perhaps UI could filter further so "one warning per project"? [Keep in mind, I barely know what you are talking about :) ] But, seems worth opening "enhancement request" and could be discussed there in detail, and implemented later after getting some experience? MY question is ... different topic ... this fix is currently in N-builds, right? and the first "versioned" one will be in next Tuesday's I-build (4/8). Would it be a good idea to move up to that version as the compiler we use in our production builds (before M7) just so it gets a little more exercise? Or, should I wait another week or so? [Our M7 stabilization week begins 4/27, so we have about 3 weeks left -- my main concern is I do think this should be used at least a week or two before M7, just to make sure we don't have any surprises in our delivered M7 compiler.] Thanks,
(In reply to David Williams from comment #44) > MY question is ... different topic ... this fix is currently in N-builds, > right? and the first "versioned" one will be in next Tuesday's I-build > (4/8). Would it be a good idea to move up to that version as the compiler we > use in our production builds (before M7) just so it gets a little more > exercise? Yes.
*** Bug 432205 has been marked as a duplicate of this bug. ***
(In reply to Dani Megert from comment #45) > (In reply to David Williams from comment #44) > > MY question is ... different topic ... this fix is currently in N-builds, > > right? and the first "versioned" one will be in next Tuesday's I-build > > (4/8). Would it be a good idea to move up to that version as the compiler we > > use in our production builds (before M7) just so it gets a little more > > exercise? > > Yes. I'll document details in bug 432382. But will plan on updating for Wednesday night's N-build ... unless someone says otherwise (such as after seeing unit tests, or something).
*** Bug 432087 has been marked as a duplicate of this bug. ***
Manju mentioned a somewhat similar issue when a static/default interface methods are accessed from a 1.7 project through eclipse project dependency. Has this already been discussed somewhere? In this case, the error messages seem to be either wrong or inconsistent.
(In reply to Jayaprakash Arthanareeswaran from comment #49) > Manju mentioned a somewhat similar issue when a static/default interface > methods are accessed from a 1.7 project through eclipse project dependency. > Has this already been discussed somewhere? In this case, the error messages > seem to be either wrong or inconsistent. Do we have a bug for that?
The change in this bug is not specific to the JRE, so I'd expect things to be consistent with project dependencies. Example?
(In reply to Stephan Herrmann from comment #51) > The change in this bug is not specific to the JRE, so I'd expect things to > be consistent with project dependencies. Example? A 1.8 project has this: public interface I8 { static String staticM1(File f){ return "static"; } default String defaultM2(File f){ return "static"; } } And a 1.7 level project has the other project in it's build path and has this: import p1.I8; public class A7 { static String foo(I8 i, File f) { I8.staticM1(f); // Reported [1] i.defaultM2(f); // Not reported [2] return "instance"; } public static void main(String[] args) { foo(new I8(){}, new File("c:\\temp\temp.txt")); } } [1] says static methods should be invoked in a static way. When this line is commented out and run, the default method invocation results in a run time error. (class version mismatch)
(In reply to Jayaprakash Arthanareeswaran from comment #52) > [1] says static methods should be invoked in a static way. While this is not the optimal error, I don't see how a static interface method could ever be called from a 1.7 project. I don't think we should invest in this case. > When this line is > commented out and run, the default method invocation results in a run time > error. (class version mismatch) Are you seeing this? : "Exception in thread "main" java.lang.UnsupportedClassVersionError: p1/I8 : Unsupported major.minor version 52.0" This is exactly what I expect when trying to run 52.0 files on a JVM7. On JVM8 the program executes flawlessly. => What behavior *are* you expecting?
(In reply to Stephan Herrmann from comment #53) > (In reply to Jayaprakash Arthanareeswaran from comment #52) > > [1] says static methods should be invoked in a static way. > > While this is not the optimal error, I don't see how a static interface > method could ever be called from a 1.7 project. I don't think we should > invest in this case. This was my only concern. Although, I agree for such a wrong set up, it's not worth spending time. Manju, what do you think? > This is exactly what I expect when trying to run 52.0 files on a JVM7. On > JVM8 the program executes flawlessly. > > => What behavior *are* you expecting? I am fine with this, actually.
I agree with Stephan an Jay that we don't have to do anything special for the case where 1.7 code refers to 1.8 features. The goal of this bug was to support compilation of 1.7 code against dependencies that declare 1.8 features, but not to support actual usage of those 1.8 features. In that case, the depending 1.7 project should be bumped to 1.8. If it can't do that, then it simply can't use the new APIs. That's totally OK, since there's no way to run a 1.8 class file on a 1.7 VM anyway.
(In reply to Markus Keller from comment #55) > I agree with Stephan an Jay that we don't have to do anything special for > the case where 1.7 code refers to 1.8 features. > > The goal of this bug was to support compilation of 1.7 code against > dependencies that declare 1.8 features, but not to support actual usage of > those 1.8 features. In that case, the depending 1.7 project should be bumped > to 1.8. If it can't do that, then it simply can't use the new APIs. That's > totally OK, since there's no way to run a 1.8 class file on a 1.7 VM anyway. +1.
Tested out the examples mentioned in Comment 1 and Comment 15. The examples compiled without any errors. Verified for 4.4 M7 using I20140427-2030 build.
(In reply to Stephan Herrmann from comment #53) > (In reply to Jayaprakash Arthanareeswaran from comment #52) > > [1] says static methods should be invoked in a static way. > > While this is not the optimal error, I don't see how a static interface > method could ever be called from a 1.7 project. I don't think we should > invest in this case. Streams API is an example. Several factory methods are on java.util.stream.Stream and the classes they instantiate are package protected.
(In reply to Philippe Marschall from comment #58) > (In reply to Stephan Herrmann from comment #53) > > (In reply to Jayaprakash Arthanareeswaran from comment #52) > > > [1] says static methods should be invoked in a static way. > > > > While this is not the optimal error, I don't see how a static interface > > method could ever be called from a 1.7 project. I don't think we should > > invest in this case. > > Streams API is an example. Several factory methods are on > java.util.stream.Stream and the classes they instantiate are package > protected. This doesn't justify that a 1.7 project should be allowed to access any of this Java 8 specific stuff. If you depend on API from JRE8, you need a 1.8 compiler.
(In reply to Stephan Herrmann from comment #59) > (In reply to Philippe Marschall from comment #58) > > (In reply to Stephan Herrmann from comment #53) > > Streams API is an example. Several factory methods are on > > java.util.stream.Stream and the classes they instantiate are package > > protected. > > This doesn't justify that a 1.7 project should be allowed to access any of > this Java 8 specific stuff. If you depend on API from JRE8, you need a 1.8 > compiler. We use a JRE8 and a 1.8 compiler but we keep the source level at 1.7 because various tools are not ready yet.
(In reply to Philippe Marschall from comment #60) > We use a JRE8 and a 1.8 compiler but we keep the source level at 1.7 because > various tools are not ready yet. In comment#59, Stephan means a 1.8 source level project, not merely a compiler that *can* compile 1.8