A problem with build task and sourceCompatibility = 1.7, gradle 5.3 - java

I use sourceCompatibility = 1.7 in gradle.properties, Gradle JVM(Settings, Gradle, Intellij IDEA) is 1.8.0_171 and
wrapper {
gradleVersion = '5.3'
distributionType = 'ALL'
}
in build.gradle.
When I run build task(Tasks->build->build Intellij IDEA) I get "error: incompatible types: inferred type does not conform to equality constraint(s)" during compileJava task.
If I set up Gradle JVM is 1.7.0_80 and
wrapper {
gradleVersion = '4.3'
distributionType = 'ALL'
}
build is fine.
What I'm doing wrong? How can I build JAVA 7 project using gradle 5.3?

This is probably caused by a subtle change in the type-checking rules for generics between Java 7 & Java 8 as described in Why does this program compile with Java 7 but not Java 8?
So what is the solution?
I doubt you will find a magic compiler switch or something to just make it work. Realistically, I think that your choices are:
You could just compile on a Java 7 platform as you did to start with. But this is not a good long-term solution.
If this is a supported product, lodge a support request.
If this is an open source product, check the product's issue checker to see if someone has already reported the problem. They may have reported a fix as well.
Look at the source code that you are trying to compile, identify the cause of the compilation error and fix it. If this is an open source product, submit your fix as a patch.
Note that it is possible that these compilation errors are reporting a latent bug that could under some circumstances lead to unexpected runtime exceptions.
You said:
I thought sourceCompatibility = 1.7 will set up java 7 for compile *.java.
It does. However, there are degrees of compatibility.
When you run a Java 8 compiler with -source 1.7 you are actually just turning off support for new language features. Under the hood, the compiler is still a Java 8 compiler. If there have been subtle changes in (for example) the type checker, it is plausible that the Java engineers did not implement a backwards compatibility mode for the old behavior.
(The extra mode may make an already complex piece of software too difficult to maintain. Type checking and type inference is one of the more difficult aspects of compiler implementation.)

Related

Scala build error on Java 11 using intellijidea

When I build my project from IntellijIdea I get the following errors
Error:scalac: 'jvm-11' is not a valid choice for '-target'
Error:scalac: bad option: '-target:jvm-11'
I am using gradle to build my project. My project is using java 11 and scala 2.12.8.
Can someone help me resolve this error?
Scala 2.12 doesn't support JVM 11 as a target. You need to add this to your gradle build file:
tasks.withType<ScalaCompile> {
targetCompatibility = "1.8"
}
As for Scala 2.13, the fix for this issue is:
tasks.withType<ScalaCompile>() {
targetCompatibility = ""
scalaCompileOptions.additionalParameters = listOf("-target:11")
}
In my case, I simply had Scala misconfigured after Idea update.
Scala 12 can in fact be compatible with Java 11. It's better to check compatibility table.
I had to remove my previous Scala library from Project Structure and re-added it as described in this answer.
This is due to a bug in IntelliJ (or IntelliJ's Scala plugin):
https://youtrack.jetbrains.com/issue/SCL-18813
I have posted there a workaround, which was inspired by IvanoBulo's answer above.

assert keyword(cannot resolve symbol assert)

GridBlock firstBlock =grid.getEntranceBlock(); //enter through entrance
assert(firstBlock!=null);
The above assert keyword is flaged by the IDEA and I don't understand why. If i try to compile i get an warning "Warning:(83, 25) java: as of release 1.4, 'assert' is a keyword, and may not be used as an identifier
(use -source 1.4 or higher to use 'assert' as a keyword)". As I understand you can use assert without having to import anything. Now i don't understand what I am missing. I tried download new JDK but it didn't help. I m using Intellij
Check what "language level" your project is using: File > Project Structure > Project > Project language level
You might be on a very old level for some reason. If there's no reason to be on it, just try increasing it to something more modern -- this will also give you other very useful language features.

Null analysis in eclipse compatibility break between 7 and 8

I have encountered strange behaviour of nullcheck analysis under Spring tool suite 3.6.2 (Eclipse clon) on windows 7 64bit with Oracle java 8u25. The same maven project with java 7 source compatibility successfully finds NPE error in eclipse, but when I change compilation version in maven to java 1.8, the eclipse is unable to find this error.
My nullcheck analysis configuration in Eclipse (Java->Compiler->Errors/Warnings->Null analysis) is:
Include asserts in null analysis true
Enable annotation based analysis true
NotNull custom annotation is properly set to javax.validation.constraints.NotNull
etc. (everything seems to be OK, as it works under java 7)
My maven pom is here http://pastebin.com/pF1yJSG2 , as mentioned above when java.version in pom is 1.7 null check works, when is 1.8 null check does not work.
Sample source code is:
package test.nullcheckbug.core;
import javax.validation.constraints.NotNull;
public class Program {
/**
* This will fail to compile under java 7 (null analysis works in STS
* 3.6.2). But under java 8 it does not show error in Eclipse Markers -
* static analysis does not work ?!
*
* #return null which is not allowed
*/
#NotNull
public String fail() {
return null;
}
/**
* Simple main.
*
* #param args
* ignored args
*/
public static void main(String[] args) {
}
}
Does anybody know where is problem and how to enable nullcheck to work under jdk 1.8 compatibility ?
EDITED:
Maven seems to be not involved. The same problem simulated on non maven project with the same source code and compatibility level of compiler set to 1.7. Is it a bug ?
EDITED-2:
After more examination I have found that the following difference in annotation makes difference : java.lang.annotation.ElementType.TYPE_USE , when annotation does not have this, the nullcheck is not detected under Java 8, but is detected under Java 7.
But why ?! Why there is so different behaviour ?!
EDITED-3:
After research from MartinLippert and tested by me it seems that nullcheck API has drastically changed between java 7 and java 8. Null detection requires (as seen from version 2.0 of eclipse libraries) java.lang.annotation.ElementType.TYPE_USE, the types #Target(value={METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER}) are ignored in analysis. SO THE QUESTION IS NOW AS FOLLOWS: WHY NULL ANALYSIS UNDER JAVA 8 REQUIRES AND WORKS ONLY UNDER NEW ELEMENT TYPE ? (I understand that with java 8 it is good to fully utilise new language features, but why was needed to break compatibility ? For example javax.validation #NotNull is now unusable as nullchecking annotation :-((( )
For Eclipse Luna, the development effort was focused on the "typical" combinations:
Java 7 and declaration annotations
Java 8 and type annotations
In this version the combination Java 8 and declaration annotations (what is requested in this question) was not fully implemented.
This has been fixed via https://bugs.eclipse.org/bugs/show_bug.cgi?id=435805
The fix is available in milestone builds towards Eclipse Mars since M4.
OTOH, I can only encourage projects using Java 8 to upgrade to type annotations for much greater expressiveness - enabling much more precise null type checking.

Syntax error, 'for each' statements are only available if source level is 1.5 or greater

Receiving the below error:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Syntax error, 'for each' statements are only available if source level is 1.5 or greater at Tuto.OneDimArrays.main(OneDimArrays.java:14)
CODE:
public class OneDimArrays {
public static void main(String[] args) {
int[] xabc = new int[5];
xabc[2]=20;
xabc[0]=50;
for(int temp:xabc){
System.out.println(temp);
}
}
}
Please help..
If you are using Eclipse IDE then right click on the project, goto properties, Java Compiler, Check Enable project specific settings and set the Compiler compliance level to greater than 1.5. I solved this issue by setting it to 1.6.
Hope it helps
The error tells you exactly what the problem is. You are using a for-each loop:
for(int temp : xabc)
{
System.out.println(temp);
}
This syntax was only added in Java 1.5, so you appear to be compiling using an earlier version. Without knowing what IDE/environment you're using, I can't tell you how to fix this, but see if you can find a way to compile your code using a more up-to-date version of java.
Note that there is a difference between the JRE (Java Runtime Environment) and the JDK (Java Development Kit). The JRE is used to run java programs on your computer, while the JDK is used to write java programs on your computer. Normally your system only warns you when the JRE is outdated (as most computer users don't write code and probably don't even have the JDK installed). Therefore, even if your JRE is up to date, you won't be able to compile the latest features unless you have the right JDK.
If you're using an old JDK, you can download the latest version here.
If you're using an up-to-date JDK, you will have to change some settings in your project in order to use it.
If for whatever reason neither of these are an option, you can emulate the for-each loop using pre-1.5 language constructs. The most basic approach is described in Pat's answer.
Compile this in a later version of java if you can.
If you are unable to use a later version of java for some reason just use a regular for loop:
for(int i = 0; i < xabc.length; i++) {
int temp = xabc[i];
System.out.println(temp);
}
Try changing compiler compilance level in eclipse:-
click Windows , go to preferences.
select java from the options ,select compiler in drop down menu.
change compiler compilance level to a value 1.5 or greater.
click on the link for reference: https://i.stack.imgur.com/79tvV.png
This is for eclipse.
window -> preferences -> java -> compiler -> configure project specific settings -> double click on created 'project name' -> uncheck 'use compliance from execution environment' -> then select 'compiler compliance level' to 1.5 or higher(best to choose the last level which is maximum and latest)
Done. now apply and close all. re run the program.

Java backward compatibility doesn't work

I've created library for encoding/decoding property files. Library has two main purposes:
Encode property file and save it to another file.
Return key value from encoded file (decode file, store result as string in memory, load string to Properties object and return result from properties object).
Everything seems to work fine but today I've noticed that library doesn't work on java 1.5. I've noticed that problem occurs on decoding side so let's focus on this code. Assume that code responsible for decoding looks like that:
String props = "key1=val1\nkey2=val2";
Properties p = new Properties();
p.load(new StringReader(props));
p.list(System.out);
After few tests I saw that the problem is with this line:
p.load(new StringReader(props));
I found that Properties class in java 1.5 doesn't have load(Reader) declaration. To meet java 1.5 API requirements I changed this line to load(InputStream). Everyting works fine now but here is the question.
I use gradle to compile project and I knew that this library should work on java 1.5+ ( I've java 1.7 installed on my computer) so I added to build.gradle those two lines
sourceCompatibility = '1.5'
targetCompatibility = '1.5'
I thought that java compiler will know that I want to compile code with compatibility to java 1.5 and will show appropriate errors. To be sure that it isn't gradle problem I compiled java code from command line but with the same result (compiler doesn't show any errors). So why compiler doesn't show any errors while compiling?
Java 1.5 Properties class API: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html
Java 1.6 Properties class API: http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html
[UPDATE]
Neither -source or -target will check API compatibility. If so how can I check it in gradle? As millimoose wrote maven has this plugin (http://mojo.codehaus.org/animal-sniffer-maven-plugin/index.html) but what with gradle?
See the sections of the javac documents named "cross-compiling" and "Cross-Compilation Example".
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html#crosscomp-options
Specifically this part:
It is important to use -bootclasspath and -extdirs when
cross-compiling; see Cross-Compilation Example below ....... If you do not
specify the correct version of bootstrap classes, the compiler will
use the old language rules (in this example, it will use version 1.6
of the Java programming language) combined with the new bootstrap
classes, which can result in class files that do not work on the older
platform (in this case, Java SE 6) because reference to non-existent
methods can get included.
The -source switch only instructs the compiler to give a compilation error if you use a language construct not supported in the specified version. For example using try-with-resources with -source 1.6 will result in a compilation error, as it is only supported in Java 7 and higher. Its use is more a sanity check (ie: is my code still compatible with Java version 1.x)
The -target switch instructs the compiler to emit byte code compatible with the specified version. That is: the compiled code can run on the virtual machines of the specified version.
However neither of these switches make the compiler check for compatibility with Java libraries of an earlier Java version. That is why since Java 7, the compiler gives a warning if you use -target 1.6 (or earlier), that you should also specify the -bootclasspath to point to a Java runtime library set of that java version so that it can check if your code is only using classes and methods of that Java version.

Categories

Resources