You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Garret Wilson <ga...@globalmentor.com> on 2023/01/31 16:13:58 UTC

changes in Tomcat 10 break Spring Boot 3 executable JARs

I'm passing on an issue discussed on Spring Boot GitHub which may not 
have been passed on to you. The main ticket is 
https://github.com/spring-projects/spring-boot/issues/33633 .

Spring Boot 3 executable JARs with Java 17 will break with 
"java.lang.IllegalStateException: zip file closed" when Tomcat 10 tries 
to start. You can see an example stack trace at 
https://github.com/spring-projects/spring-boot/issues/34028 .

Apparently Tomcat 9 used to do a JAR file multi-release check like this:

```java
@Override
public boolean jarFileIsMultiRelease(JarFile jarFile) {
     try {
         return ((Boolean) 
isMultiReleaseMethod.invoke(jarFile)).booleanValue();
     } catch (ReflectiveOperationException | IllegalArgumentException e) {
         return false;
     }
}
```

In Tomcat 10.1 it looks like this:

```java
multiRelease = jarFile.isMultiRelease();
```

I don't know anything about this code (I'm merely passing on what is in 
the ticket), but I can guess that Tomcat wants to get away from 
reflective operations, especially with later Java versions. That's fine 
and probably a good idea. Unfortunately the new code does no error 
handling whatsoever, so that the `IllegalStateException` kills 
everything. If you could at least catch the `IllegalStateException` and 
assume `false` I would imagine that would work around this issue.

The Spring Boot ticket acknowledges that they should improve their 
`JarUrlConnection` so that it wouldn't return a `JarFile` that was 
closed in the first place. Unfortunately there's no indication when that 
would be done, and right now the entire Spring Boot 3 executable JAR 
system is broken, requiring a system property to be added as a workaround.

Would you consider adding more error handling in a Tomcat 10 patch so 
that users to explicitly override the Tomcat 10 version and get their 
Spring Boot 3 executable JARs working again?

Thanks,

Garret


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: changes in Tomcat 10 break Spring Boot 3 executable JARs

Posted by Rémy Maucherat <re...@apache.org>.
On Tue, Jan 31, 2023 at 5:14 PM Garret Wilson <ga...@globalmentor.com> wrote:
>
> I'm passing on an issue discussed on Spring Boot GitHub which may not
> have been passed on to you. The main ticket is
> https://github.com/spring-projects/spring-boot/issues/33633 .
>
> Spring Boot 3 executable JARs with Java 17 will break with
> "java.lang.IllegalStateException: zip file closed" when Tomcat 10 tries
> to start. You can see an example stack trace at
> https://github.com/spring-projects/spring-boot/issues/34028 .
>
> Apparently Tomcat 9 used to do a JAR file multi-release check like this:
>
> ```java
> @Override
> public boolean jarFileIsMultiRelease(JarFile jarFile) {
>      try {
>          return ((Boolean)
> isMultiReleaseMethod.invoke(jarFile)).booleanValue();
>      } catch (ReflectiveOperationException | IllegalArgumentException e) {
>          return false;
>      }
> }
> ```
>
> In Tomcat 10.1 it looks like this:
>
> ```java
> multiRelease = jarFile.isMultiRelease();
> ```
>
> I don't know anything about this code (I'm merely passing on what is in
> the ticket), but I can guess that Tomcat wants to get away from
> reflective operations, especially with later Java versions. That's fine
> and probably a good idea. Unfortunately the new code does no error
> handling whatsoever, so that the `IllegalStateException` kills
> everything. If you could at least catch the `IllegalStateException` and
> assume `false` I would imagine that would work around this issue.
>
> The Spring Boot ticket acknowledges that they should improve their
> `JarUrlConnection` so that it wouldn't return a `JarFile` that was
> closed in the first place. Unfortunately there's no indication when that
> would be done, and right now the entire Spring Boot 3 executable JAR
> system is broken, requiring a system property to be added as a workaround.
>
> Would you consider adding more error handling in a Tomcat 10 patch so
> that users to explicitly override the Tomcat 10 version and get their
> Spring Boot 3 executable JARs working again?

After looking at the code (including in Java), it would seem this is a
bug of both Spring (bad jar) and Java (inconsistent API that returns
false on IOE, no javadoc for the possible ISE). However, I prefered
restoring the previous behavior so the ISE is now caught again and
multi release defaults to false in that case.

Rémy

> Thanks,
>
> Garret
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: changes in Tomcat 10 break Spring Boot 3 executable JARs

Posted by Rémy Maucherat <re...@apache.org>.
On Tue, Jan 31, 2023 at 5:14 PM Garret Wilson <ga...@globalmentor.com> wrote:
>
> I'm passing on an issue discussed on Spring Boot GitHub which may not
> have been passed on to you. The main ticket is
> https://github.com/spring-projects/spring-boot/issues/33633 .
>
> Spring Boot 3 executable JARs with Java 17 will break with
> "java.lang.IllegalStateException: zip file closed" when Tomcat 10 tries
> to start. You can see an example stack trace at
> https://github.com/spring-projects/spring-boot/issues/34028 .
>
> Apparently Tomcat 9 used to do a JAR file multi-release check like this:
>
> ```java
> @Override
> public boolean jarFileIsMultiRelease(JarFile jarFile) {
>      try {
>          return ((Boolean)
> isMultiReleaseMethod.invoke(jarFile)).booleanValue();
>      } catch (ReflectiveOperationException | IllegalArgumentException e) {
>          return false;
>      }
> }
> ```
>
> In Tomcat 10.1 it looks like this:
>
> ```java
> multiRelease = jarFile.isMultiRelease();
> ```
>
> I don't know anything about this code (I'm merely passing on what is in
> the ticket), but I can guess that Tomcat wants to get away from
> reflective operations, especially with later Java versions. That's fine
> and probably a good idea. Unfortunately the new code does no error
> handling whatsoever, so that the `IllegalStateException` kills
> everything. If you could at least catch the `IllegalStateException` and
> assume `false` I would imagine that would work around this issue.
>
> The Spring Boot ticket acknowledges that they should improve their
> `JarUrlConnection` so that it wouldn't return a `JarFile` that was
> closed in the first place. Unfortunately there's no indication when that
> would be done, and right now the entire Spring Boot 3 executable JAR
> system is broken, requiring a system property to be added as a workaround.
>
> Would you consider adding more error handling in a Tomcat 10 patch so
> that users to explicitly override the Tomcat 10 version and get their
> Spring Boot 3 executable JARs working again?

The initial version of the compat code already had the try/catch for
the ISE, so it would basically have worked by accident, and the result
of the method is basically not accurate (it could return false for a
multi release JAR - obviously this is not super likely to break
something since those are not that common). This compat code is now
removed since Tomcat 10.1 is Java 11+ so it has the necessary real
API. And we didn't know that the ISE was a problem. Not sure what to
do about that though ...

Rémy

> Thanks,
>
> Garret
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org