Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump up Java version to 21 #2682

Merged
merged 22 commits into from
Oct 24, 2024
Merged

Bump up Java version to 21 #2682

merged 22 commits into from
Oct 24, 2024

Conversation

iamsanjay
Copy link
Contributor

https://issues.apache.org/jira/browse/SOLR-17321

Bump up Java version to 21. Although we have decided to have different versions for Solr and SolrJ to 21 and 17 respectively. Currently in this PR, both of them are pointing to 21 to seek feedback and to test everything. Meanwhile looking for way to set SolrJ to 17.

@iamsanjay
Copy link
Contributor Author

iamsanjay commented Aug 30, 2024

This happens some time!

https://github.com/apache/solr/actions/runs/10627729009/job/29461325476?pr=2682

Task :solr:benchmark:compileJava FAILED
An exception has occurred in the compiler (21.0.4). Please file a bug against the Java compiler via the Java bug reporting page (https://bugreport.java.com/) after checking the Bug Database (https://bugs.java.com/) for duplicates. Include your program, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you.
java.lang.VirtualMachineError: Out of space in CodeCache for adapters
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next(JavacProcessingEnvironment.java:824)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:922)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1265)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1380)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1272)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:946)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
at org.gradle.internal.compiler.java.IncrementalCompileTask.call(IncrementalCompileTask.java:92)
at org.gradle.api.internal.tasks.compile.AnnotationProcessingCompileTask.call(AnnotationProcessingCompileTask.java:94)
at org.gradle.api.internal.tasks.compile.ResourceCleaningCompilationTask.call(ResourceCleaningCompilationTask.java:57)
at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:55)
at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:39)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:98)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:52)
at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38)
at

build.gradle Outdated Show resolved Hide resolved
Copy link
Contributor

@dsmiley dsmiley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW we don't have to compile with JDK 17 or use JDK 17 at all for the build. We just need to tell JDK 21 that a few modules for SolrJ are to be compiled with Java 17 language / support, allowing users on JDK 17 to use it. I don't recall the particulars of doing this.

.github/workflows/bin-solr-test.yml Outdated Show resolved Hide resolved
.github/workflows/gradle-precommit.yml Outdated Show resolved Hide resolved
.github/workflows/gradle-precommit.yml Outdated Show resolved Hide resolved
@github-actions github-actions bot added cat:cli and removed scripts labels Oct 8, 2024
@iamsanjay
Copy link
Contributor Author

./gradlew compileJava seem to work fine. Only If we find a way to set Jdk to 21 for all the test packages. Because currently, test cases from api not able to find classes from other projects that are on higher version, and that's where it's failing.

@dsmiley
Copy link
Contributor

dsmiley commented Oct 8, 2024

Note that "api" module should also be Java Language 17, as it's included with SolrJ.

@iamsanjay
Copy link
Contributor Author

Looks like below config is working. It sets solrj and related projects to Jdk17 and rest of the projects to Jdk21 for main. And, for all the test packages they are using Jdk21.

javac.gradle

    // Use 'release' flag instead of 'source' and 'target'
     tasks.withType(JavaCompile) {
       compileTestJava {
         options.compilerArgs += ["--release", JavaVersion.toVersion(scriptDepVersions['min-java-version']).toString()]
       }
       compileJava {
         options.compilerArgs += ["--release", project.minJavaVersion.toString()]
       }
     }

Now, to test it. I unpack the builds and verify it in MANIFEST.MF.

solrj

Specification-Title: Apache Solr Search Server: solrj
X-Compile-Source-JDK: 17
X-Compile-Target-JDK: 17
X-Build-JDK: 21.0.3 (Oracle Corporation 21.0.3+7-LTS-152)
X-Build-OS: Mac OS X aarch64 14.3

api

Specification-Title: Apache Solr Search Server: api
X-Compile-Source-JDK: 17
X-Compile-Target-JDK: 17
X-Build-JDK: 21.0.3 (Oracle Corporation 21.0.3+7-LTS-152)
X-Build-OS: Mac OS X aarch64 14.3

solr-zookeeper

Specification-Title: Apache Solr Search Server: solrj-zookeeper
X-Compile-Source-JDK: 17
X-Compile-Target-JDK: 17
X-Build-JDK: 21.0.3 (Oracle Corporation 21.0.3+7-LTS-152)
X-Build-OS: Mac OS X aarch64 14.3

solrj-streaming

Specification-Title: Apache Solr Search Server: solrj-streaming
X-Compile-Source-JDK: 17
X-Compile-Target-JDK: 17
X-Build-JDK: 21.0.3 (Oracle Corporation 21.0.3+7-LTS-152)
X-Build-OS: Mac OS X aarch64 14.3

core

Specification-Title: Apache Solr Search Server: core
X-Compile-Source-JDK: 21
X-Compile-Target-JDK: 21
X-Build-JDK: 21.0.3 (Oracle Corporation 21.0.3+7-LTS-152)
X-Build-OS: Mac OS X aarch64 14.3

But I would really appreciate If someone else test it and check If we able to achieve the different version for solr (Jdk21) and solrj(jdk17).

@dsmiley
Copy link
Contributor

dsmiley commented Oct 10, 2024

Nice work. I toyed with it a bit, including tinkering with toolchains. Avoiding toolchains avoids IntelliJ's Gradle's check to tell you that we really should be using a newer Gradle Version:

Your build is currently configured to use incompatible Java 21.0.4 and Gradle 8.4. Cannot sync the project.

We recommend upgrading to Gradle version 8.8.

The minimum compatible Gradle version is 8.5.

The maximum compatible Gradle JVM version is 20.

Possible solutions:
 - Upgrade to Gradle 8.8 and re-sync
 - Upgrade to Gradle 8.5 and re-sync
 - Use Java 20 as Gradle JVM: Open Gradle settings

@dsmiley
Copy link
Contributor

dsmiley commented Oct 10, 2024

Why aren't we using toolchains?: https://docs.gradle.org/current/userguide/toolchains.html

@dsmiley dsmiley mentioned this pull request Oct 10, 2024
7 tasks
@dsmiley
Copy link
Contributor

dsmiley commented Oct 10, 2024

The Docker build.gradle needs to refer to a JDK 21 base image, not JDK 17.

BTW, when I checked out your branch and before I tinkered with it, I simply tried to get IntelliJ to sync it and then view IntelliJ's module language versions to see if it would get confused on the SolrJ modules, given differing desired language levels for tests. It was confused; it thought the whole module should use JDK 17, even the test sourcepath. I suspect the issue is that we don't use proper metadata (i.e. toolchain) to convey to IntelliJ what's going on.

@github-actions github-actions bot added the docker Docker image label Oct 10, 2024
@iamsanjay
Copy link
Contributor Author

The toolchain cannot be set at the JavaCompile level. Because we are using different Jdk for main and test package. To set at project level, below is the config. But this fails!

allprojects {
  plugins.withType(JavaPlugin) {
    java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
  }
 }
}

Next, we have different toolchain for the tasks. And below is the way to configure different toolchain for compileJava and compileTestJava.

tasks.withType(JavaCompile) {
        compileTestJava {
          javaCompiler = javaToolchains.compilerFor {
            languageVersion = JavaLanguageVersion.of(JavaVersion.toVersion(scriptDepVersions['min-java-version']).toString())
          }
          options.compilerArgs += ["--release", JavaVersion.toVersion(scriptDepVersions['min-java-version']).toString()]
        }
        compileJava {
          javaCompiler = javaToolchains.compilerFor {
            languageVersion = JavaLanguageVersion.of(project.minJavaVersion.toString())
          }
          options.compilerArgs += ["--release", project.minJavaVersion.toString()]
        }
      }

This works! I ran with ./gradlew :solr:api:build --info and I can see different toolchain being loaded

Task ':solr:api:compileJava' is not up-to-date because:
  Output property 'destinationDirectory' file /Users/sanjaydutt/Documents/solr/solr/api/build/classes/java/main has been removed.
  Output property 'destinationDirectory' file /Users/sanjaydutt/Documents/solr/solr/api/build/classes/java/main/org has been removed.
  Output property 'destinationDirectory' file /Users/sanjaydutt/Documents/solr/solr/api/build/classes/java/main/org/apache has been removed.
  Output property 'options.generatedSourceOutputDirectory' file /Users/sanjaydutt/Documents/solr/solr/api/build/generated/sources/annotationProcessor/java/main has been re
moved.
The input changes require a full rebuild for incremental task ':solr:api:compileJava'.
Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments.
Compiling with toolchain '/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home'.
Compiling with JDK Java compiler API.
Class dependency analysis for incremental compilation took 0.003 secs.
Created classpath snapshot for incremental compilation in 0.0 secs.
work action resolve main (project :solr:api) (Thread[#760,Execution worker Thread 3,5,main]) started.
Resolve mutations for :solr:api:processResources (Thread[#760,Execution worker Thread 3,5,main]) started.


> Task :solr:api:compileTestJava
Caching disabled for task ':solr:api:compileTestJava' because:
  Build cache is disabled
Task ':solr:api:compileTestJava' is not up-to-date because:
  Task has failed previously.
The input changes require a full rebuild for incremental task ':solr:api:compileTestJava'.
Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments.
Compiling with toolchain '/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home'.
Compiling with JDK Java compiler API.
Class dependency analysis for incremental compilation took 0.0 secs.
Created classpath snapshot for incremental compilation in 0.003 secs.
Resolve mutations for :solr:api:analyzeTestClassesDependencies (Thread[#757,included builds,5,main]) started.

However, jar task is still, I think ,running with whatever java_home is

Because whenever I open MANIFEST.MF, Build-JDK is 21. I mean we are successfully able to compile files using jdk 17, however whenever jar task is running it's running via 21.

Specification-Title: Apache Solr Search Server: api
X-Compile-Source-JDK: 17
X-Compile-Target-JDK: 17
X-Build-JDK: (21.0.3)
X-Build-OS: Mac OS X aarch64 14.3

I try to add the toolchain config to jar-manifest.gradle, but it's not working

doFirst {
                    def toolchain = javaToolchains.compilerFor {
                        languageVersion = JavaLanguageVersion.of(project.minJavaVersion.toString())
                    }
                }
                manifest {
                    attributes([
                            "Extension-Name"        : implementationTitle,

                            "Implementation-Vendor" : "The Apache Software Foundation",
                            "Implementation-Title"  : implementationTitle,
                            "Implementation-Version": implementationVersion,

                            "Specification-Vendor"  : "The Apache Software Foundation",
                            "Specification-Version" : project.baseVersion,
                            "Specification-Title"   : title,

                            // Evaluate these properties lazily so that the defaults are applied properly.
                            "X-Compile-Source-JDK"  : "${-> project.sourceCompatibility}",
                            "X-Compile-Target-JDK"  : "${-> project.targetCompatibility}",

                            "X-Build-JDK"           : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']})",
                            "X-Build-OS"            : "${System.properties['os.name']} ${System.properties['os.arch']} ${System.properties['os.version']}"
                    ])
                }

@iamsanjay
Copy link
Contributor Author

When it comes to Intellij module language level, I am not sure How we will solve that? Given that all solrj and realted modules have two jdk versions now.

@iamsanjay
Copy link
Contributor Author

We use Toolchain to enforce the specific version of the tools we want to use. Here are some use cases:

  1. If our system's JDK is set to 21, but I want to run a project on a different Java version.
  2. If I need a specific Java version from a vendor for all tasks.
  3. If I want to run Gradle and the project on different Java versions.

In our scenario, if the system is configured with JDK 21, that version will be used to run all tasks for Solr and SolrJ. JDK 21 can generate class files with version 61 without issues. However, if we want SolrJ to compile only with JDK 17, Toolchain can accomplish that. Otherwise, the Java version used by Gradle will be applied globally.

@iamsanjay
Copy link
Contributor Author

From Intellij docs:

https://www.jetbrains.com/help/idea/gradle.html#gradle_jvm

Language level: the language level settings are applied for a source root or for a module. If a Gradle project has a single linked project then the project default language level is set to the minimum language level among the module language levels. The module language level is set to sourceCompatibility in the build.gradle file.

@iamsanjay
Copy link
Contributor Author

iamsanjay commented Oct 10, 2024

IMO, There is no way to configure toolchain for jar task like we can do for JavaCompile. Even the JarTask has no mention of compiler like JavaCompiler has.

https://github.com/gradle/gradle/blob/master/platforms/jvm/platform-jvm/src/main/java/org/gradle/jvm/tasks/Jar.java
https://github.com/gradle/gradle/blob/master/platforms/jvm/language-java/src/main/java/org/gradle/api/tasks/compile/JavaCompile.java#L202

My question is that does it even matter which jdk version actually package the class files? Given that we made sure that compileJava task ran only by appropriate jdk.

@dsmiley
Copy link
Contributor

dsmiley commented Oct 10, 2024

However, jar task is still, I think ,running with whatever java_home is

It's normal & acceptable that the entire build itself do JAR packaging etc with the same running JVM, that which Gradle is using -- JDK 21. We shouldn't try to change that or validate the manifest entry for the build JDK. It's just some FYI metadata.

RE IntelliJ -- lots of us use IntelliJ; if IntelliJ will not tolerate Java 21 language features in a SolrJ test, we'll have to use Java 17 for those tests. Okay, not a big deal.

@iamsanjay
Copy link
Contributor Author

iamsanjay commented Oct 11, 2024

gradle Auto-provisioning is disabled.

./gradlew -q javaToolchains                                                             

 + Options
     | Auto-detection:     Enabled
     | Auto-download:      Disabled

Build is failing due to that. It's like now we are basically forcing the version of tools that being used, in this case two Jdk version 17 and 21. Otherwise, If you have both version available then no issues.

> Task :solr:api:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':solr:api:compileJava'.
> Error while evaluating property 'javaCompiler' of task ':solr:api:compileJava'.
   > Failed to calculate the value of task ':solr:api:compileJava' property 'javaCompiler'.
      > No matching toolchains found for requested specification: {languageVersion=17, vendor=any, implementation=vendor-specific} for LINUX on x86_64.
         > No locally installed toolchains match and toolchain download repositories have not been configured.

There is a way to enable it via gradle.properties. (I have to check how I can make this file change on crave, it's not picking it up.)

# Disable auto JVM provisioning (we don't use toolchains yet but want no surprises).
org.gradle.java.installations.auto-download=false

There is somewhat related discussion regarding the same in alternative-jdk-support.gradle.

// This adds support for compiling and testing against a different Java runtime.
//
// I failed to set it up leveraging Gradle's toolchains because
// a toolchain spec is not flexible enough to provide an exact location of the JVM to be used;
// if you have two identical JVM lang. versions in auto-discovered JVMs, an arbitrary one is used (?).
// This situation is not uncommon when debugging low-level stuff (hand-compiled JVM binaries).
//
// The code below is a workaround using internal gradle classes. It may stop working in the future
// but for now it's fine.
JavaInfo jvmGradle = Jvm.current();

@dsmiley
Copy link
Contributor

dsmiley commented Oct 11, 2024

I might have misunderstood Toolchains; if it means having additional JDKs around then I don't think we want to require that. It's sufficient to have only JDK 21 and configure the language level for certain parts.

@dsmiley
Copy link
Contributor

dsmiley commented Oct 15, 2024

As I mentioned, IntelliJ isn't recognizing the language distinction between tests vs non-tests so I recommend simply using the same language per module. Other than that, I suppose it's ready to merge.

At some point (could be now), we should review all the extra options we pass to java when starting Solr to see if they are still sensible. Some may be obsolete.

@iamsanjay
Copy link
Contributor Author

-XX:-UseBiasedLocking removed in JDK 21. And, due to which Benchmarking is failing. Will be removing it.

solr/bin/solr.in.sh Outdated Show resolved Hide resolved
Copy link
Contributor

@epugh epugh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I love seeing lots of "workarounds" going away! Java21 is going to let us move to the latest OpenNLP and do some cool things with ONNX for ML models..

@iamsanjay iamsanjay merged commit d840a3b into apache:main Oct 24, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants