Hi,

since JDK 17 is around the corner, I want to raise this issue to talk about the necessary steps for supporting JDK 17. I would again volunteer to help out here.

Given the impact of https://openjdk.java.net/jeps/403 we should probably start a little earlier than usual as we might need to reach out to libraries that Boot is integrating with.

Known issues so far from the top of my head - in no particular order:

  1. JsonbTesterTests.writeArrayShouldReturnJsonContent() fails due to JOHNZON-347
  2. JavaVersion should get a new entry SEVENTEEN - see #26769
  3. Multi-Release Jar tests fail - see #27229
  4. Gradle Plugin Tests fail - as usual for newer JDKs. See https://github.com/gradle/gradle/issues/16857
  5. CLI tests are failing because it's impossible to clear URL.factory via reflection - possible workaround would be to open java.net to the unnamed module. I don't see a cooler way here at the moment. Ideally TomcatURLStreamHandlerFactory.disable() would work, but my first tests didn't succeed. See #26930
  6. Similar problem as 5. but in AbstractServletWebServerFactoryTests.tearDown() - Possibly similar solution with opening modules. See #27089
  7. JarFileTests.jarFileEntryWithEpochTimeOfZeroShouldNotFail() fails because it tries to set xdostime on ZipEntry, which is internal. We could disable that test for JDK 17 and higher or again fiddle around with opening up modules. See #27100
  8. Two tests in RabbitAutoConfigurationTests fail because they are trying to access the contextSpi field on SSLContext. See #26954
  9. Generally we can't use --illegal-access=warn anymore. The option will be ignored, so it needs to be removed. See #27089
  10. ConditionalOnSingleCandidateTests.singleCandidateOneScopedProxyCandidate() fails because of the following. Haven't looked deep enough yet to see who should do what here.
 Caused by: java.lang.IncompatibleClassChangeError: class jdk.proxy3.$Proxy583 cannot implement sealed interface java.lang.constant.ConstantDesc
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.System$2.defineClass(System.java:2259)
    at java.base/java.lang.reflect.Proxy$ProxyBuilder.defineProxyClass(Proxy.java:560)
    at java.base/java.lang.reflect.Proxy$ProxyBuilder.build(Proxy.java:670)
    at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:440)
    at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
    at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
    at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:438)
    at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1032)
    at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:126)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.aop.scope.ScopedProxyFactoryBean.setBeanFactory(ScopedProxyFactoryBean.java:117)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1808)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1773)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
    ... 110 more

    at org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidateTests.lambda$singleCandidateOneScopedProxyCandidate$2(ConditionalOnSingleCandidateTests.java:60)
  1. DevToolsWithLazyInitializationIntegrationTests.exploded remote is flaky with this stacktrace (might be unrelated to JDK 17)
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
    at java.base/java.util.ArrayList.shiftTailOverGap(ArrayList.java:748)
    at java.base/java.util.ArrayList.batchRemove(ArrayList.java:839)
    at java.base/java.util.ArrayList.retainAll(ArrayList.java:811)
    at ch.qos.logback.classic.LoggerContext.resetListenersExceptResetResistant(LoggerContext.java:305)
    at ch.qos.logback.classic.LoggerContext.reset(LoggerContext.java:227)
    at ch.qos.logback.classic.LoggerContext.stop(LoggerContext.java:348)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.stopAndReset(LogbackLoggingSystem.java:196)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadDefaults(LogbackLoggingSystem.java:144)
    at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:83)
    at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:132)
    at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:312)
    at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:281)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:239)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:216)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
    at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:82)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:63)
  1. ~~Asciidoctor is apparently not running through because of the following. Maybe even unrelated~~ (Clean build fixed it):
Juni 04, 2021 6:08:14 NACHM. uri:classloader:/gems/asciidoctor-pdf-1.5.3/lib/asciidoctor/pdf/converter.rb traverse_list_item
INFORMATION: possible invalid reference: dependency-versions

There will be likely more that I might have overseen but I will add this to this issue once I encounter it. I'd like to get the low hanging fruits 2.) and 3.) out of the way. If you don't mind I would open a PR for those already.

Let me know what you think. Cheers, Christoph

Comment From: dreis2211

I think 10.) needs to be addressed in Spring-Framework. Essentially it retrieves all interfaces of String which also includes ConstantDesc which is a sealed interface and cannot be used when creating a proxy. See ScopedProxyFactoryBean.setBeanFactory:


        if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
                         // This should filter sealed interfaces I guess
            pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
        }

I'm not sure if a String bean is a valid case anyhow, but when I'm assuming that it is, this needs to be addressed.

I've opened https://github.com/spring-projects/spring-framework/issues/27027 to track Java 17 for Spring Framework.

Comment From: dreis2211

Johnzon 1.2.14 was released recently that should fix point 1 in my list. I didn't open an issue for that one because it's likely picked up by the bomr dependency upgrades, but let me know if I can do so to ease my local testing.

Comment From: wilkinsona

Thanks, @dreis2211. I've just done a round of upgrades on 2.5.x, including Johnzon 1.2.14.

Comment From: dreis2211

@wilkinsona Aren't those changes merged to main usually?

Comment From: snicoll

@dreis2211 we don't merge dependency upgrade but run bomr on each branch. We're going to apply that soon. Does that block you from experimenting in 2.5.x ?

Comment From: dreis2211

No, was just wondering.

Comment From: dreis2211

I've either reported, opened PRs or referenced the corresponding issues for every point in the original post. If I subtract my open PRs from the equation the following two things are blocking us from creating the pipeline: - Once again Gradle - see https://github.com/gradle/gradle/issues/16857 - The issue with sealed interfaces on Spring-Framework - see https://github.com/spring-projects/spring-framework/issues/27027

I could probably work around both of them by disabling the specific test(-suites) on JDK 17 or we just wait for those two before we can create the pipeline. Let me know what you prefer.

Comment From: dreis2211

The good news is that the Spring Framework issue was solved earlier than anticipated. The bad news is that Gradle calls like the following will fail on JDK 17 - see https://github.com/gradle/gradle/issues/16857#issuecomment-877360825

Project project = ProjectBuilder.builder().withProjectDir(projectDir).build();

So it's not just testing the compatibility with a specific version, but probably raising the Gradle version - which makes it hard(er) to backport to 2.5.x. I'm not sure if just excluding the failing spring-boot-gradle-plugin tests might be the best thing for now.

Also: https://github.com/spring-projects/spring-boot/commit/18c7c0af222f23c556c52162aa6348ad4b38267a moved the Gradle versions to a specific class but only in main, so 2.5.x and main are different now. Do you want me to open two PRs then?

Comment From: wilkinsona

I'm not sure if just excluding the failing spring-boot-gradle-plugin tests might be the best thing for now

Yes, I think it would be. Until Gradle catches up, no one will be able to use the plugin on JDK 17 anyway so we're not risking much by not testing it for the time being.

Do you want me to open two PRs then?

Thanks for the offer, but we're more than happy to adapt a 2.5.x PR when we merge it forwards.

Comment From: wilkinsona

Thanks for all your help here, @dreis2211.

I've turned this isn't a documentation issue as I think that's all that remains. I've also labelled it as blocked as we don't want to document support until Java 17 has GAed.

Comment From: dreis2211

Well, the Gradle plugin is not tested yet due to Gradle not supporting 17. But we had this in the past as well, so I see no problem turning this into a documentation issue.