Comments (29)
Another option is to track "vendor + major + minor" and allow the user to switch it off. They can re-add any parts of the version number as an input to the task if they want to track that.
from gradle.
We now take the following into account as inputs:
If no toolchain is configured:
- Java language version (major version)
If toolchains are configured:
- Java language version (major version)
- Vendor, if specified as toolchain requirement (starting with 6.8)
- JVM implementation (e.g. J9), if specified as toolchain requirement (starting with 6.8)
As an example, using the following setup
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.ADOPTOPENJDK
}
}
Compile and test tasks (and any custom tasks using toolchains) take 11 and the vendor into account. Wit this, we're closing this issue for now until there is a good reason to take more nuanced version information into account that is not possible to workaround as described above.
from gradle.
We should at least track the vendor.
from gradle.
Just think of IBM JDK 6!
from gradle.
This is important for Java compilation, and also for running tests.
from gradle.
We might be doing something by tracking the classpath.
from gradle.
need to confirm that rt.jar is hashed
from gradle.
We have everything we might need in rt.jar
:
Manifest-Version: 1.0
Implementation-Vendor: Oracle Corporation
Implementation-Title: Java Runtime Environment
Implementation-Version: 1.8.0_101
Specification-Vendor: Oracle Corporation
Created-By: 1.7.0_07 (Oracle Corporation)
Specification-Title: Java Platform API Specification
Specification-Version: 1.8
from gradle.
Note that we use should use the same strategy for the test task: https://github.com/gradle/build-cache/issues/145.
from gradle.
We also need to keep in mind what to do for forking Java compilation. Currently, we just pretend that we do not fork - i.e. we use the Java version of the Gradle JVM as input. This is just plain wrong.
As a workaround in the Gradle build we ignore the executable in the fork options and override the version of the tool chain.
We also need to consider if we want to have fork options as an input at all - given that we should have the same compilation result no matter if we are forking or not.
from gradle.
☝️ We now have proof that even different Oracle Java update versions (7u45 vs 7u80) produce different outputs. This is a strong reason to track the full version number along with the vendor.
from gradle.
We think it's manageable for 3.3 to live with just tracking <major>.<minor>
(e.g. 1.8
). We can track more in 4.0 if we decide that's what we want.
from gradle.
Currently, we track the Java version of the JVM Gradle runs with (JavaVersion.current()
). We need to track the Java version of the forked JVM (forkOptions.executable).
from gradle.
We are now using the JvmVersionDetector
to obtain the version of the JVM used for compilation and testing. This currently only includes the version itself. In order to obtain the vendor, we would need to use features currently only present in JavaInstallationProbe
.
from gradle.
@vydra it seems you needed this at some point. Can you explain the use case please?
from gradle.
@lptr I just wanted to make sure that we use exactly the same version for cache key. Many customers re-write bytecodes and different javac versions may produce different results.
from gradle.
We don't. We use the major version only, so we treat any minor/patch version of the compiler the same. We also treat all vendor (IBM JDK, Oracle JDK and OpenJDK, etc) compilers as the same.
from gradle.
To be clear: we are planning to change that, but probably not in 4.0.
from gradle.
@wolfs you said that you are not completely convinced about tracking the full version number (https://github.com/gradle/task-output-cache/issues/645#issuecomment-302373098). Could you explain your reasoning?
from gradle.
We have various aspects here: We track the version number of Java for compilation and for runtime. We also want to support pulling results for developers and having "perfect" results on CI.
For compilation we saw that sometimes differences in the produced bytecode for different minor version numbers. I am pretty confident that the bytecode is still the same with respect to CompileClasspath
snapshotting. So I guess only the major version matters.
For test execution, runtime classpath snapshotting still would detect differences between the bytecode. But once again I believe that the differences should treated as the same - we could improve our runtime classpath snapshotting for this case.
Treating the minor number always as an input would it make very hard for developers to pull from the cache. We saw that even in bigger companies different developers on the same team were using different Java versions. We could force them have to use the same Java version but I am not sure that this is what we want to do here.
I could even imagine that developers could somewhat say that they do not care about the minor version number when pulling from the cache while CI would only pull results with the same minor number for the cache. Our current cache interface would not support this currently, but I wouldn't discard this as an option because of this.
Having said all this it is somewhat difficult to come up with a default
strategy for tracking the Java version number which is the same in all the above situations. There are different compromises which we need to weigh against each other.
from gradle.
Thanks, this all makes sense.
I guess there's the option to allow configuring whether you want the update version tracked. That would apply to CI and developers alike, which I'm not sure is a bad idea.
In general I'm against treating CI builds different to local builds. If you take the long view, with distributed builds there will only be builds happening somewhere. Provisioning the Java version used is also not impossible. There are lots of options, we probably should support multiple of these.
FTR, one scenario where update version matters a lot is if there's an important fix in the JDK. Since we don't track the update version, upgrading the JDK on CI would not force anyone to recompile, as they could still pull the previously compiled class files from cache.
from gradle.
from gradle.
In general I agree with @vydra's long-term vision. Though we won't ever be able to fully require everyone to use a provisioned container or something. One of the major advantages of Gradle is its graceful degradation: instead of prescribing how things should work, we give you a list of requirements that if you can fulfill, then we give you excellent service. If you can't fulfill some of them, we still give you pretty good service, though you might need to sacrifice some features or performance.
For the short term Gradle offers squat right now wrt provisioning, so we can't rely on that anyway. We need to figure out how to make this work. We can require external provisioning for example. There's lots of options. The most important would be to let users know if they are using the wrong Java version for whatever reason, whether or not we'd be tracking the full version number.
from gradle.
As soon as we track the vendor we can remove the custom inputs added here: 06c5da7
from gradle.
Here's a comparison between some files compiled with Oracle Java compiler 7u45 vs 7u80:
https://github.com/lptr/javac-diff-7u45-vs-7u80/compare/u80
Several of the files end up being different byte-by-byte, mostly because of their constant tables are organized somewhat differently. I didn't add a javap
file for each difference.
from gradle.
Talked to @adammurdoch about this. He thinks we should offer a way to configure Java version normalization. I would go with these options:
- vendor + major + minor (default)
- vendor + major
- major
- ignore completely
from gradle.
Thanks for sharing; @big-guy and I discussed this in some detail in a private forum. I'll be watching to see how this evolves!
from gradle.
For the record, the workaround for tracking the vendor is described at https://guides.gradle.org/using-build-cache/#java_version_tracking.
from gradle.
This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. If you're interested in how we try to keep the backlog in a healthy state, please read our blog post on how we refine our backlog. If you feel this is something you could contribute, please have a look at our Contributor Guide. Thank you for your contribution.
from gradle.
Related Issues (20)
- java.util.concurrent.ExecutionException: org.gradle.api.GradleException: Failed to create Jar file HOT 4
- Intermittent failure to move temporary workspace to immutable location in Gradle 8.7 on Windows HOT 3
- Fix Documentation tests that are not configuration cache compatible and remove load-after-store flag
- Fix Native Platform tests that are not configuration cache compatible and remove load-after-store flag
- Fix JVM platform tests that are not configuration cache compatible and remove load-after-store flag
- Fix Extensibility platform tests that are not configuration cache compatible and remove load-after-store flag
- TestNG's threadPoolFactoryClass parameter broken for TestNG >= 7.10 HOT 1
- Support to @Inject a SoftwareComponentFactory into a BuildService
- Set applicationDefaultJvmArgs default value to stdout.encoding=UTF-8 on Windows HOT 3
- Gradle should warn users in case of conflicting ArtifactTransform registrations HOT 1
- Deadlock while resolving dependencies with excludes HOT 1
- Ensure vanilla Java applications produced by `gradle init` work with Isolated Projects out of the box HOT 3
- Allow DerivedArtifact to expose a getExtension()
- If dependency project has no variants, mention that there are none HOT 2
- Build cache problems on Windows CI agents: "Could not read workspace metadata" HOT 2
- Useful error message for PKIX path building failure with standard switches HOT 6
- Extract internal Gradle Service Injection framework into separate subprojects
- Lazy nested properties vs domain object containers HOT 3
- Poor performance of SourceDistributionProvider on the cold start HOT 4
- Gradle8.8 RC1 Still Not Support JDK22? HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gradle.