JetBrains / JetBrainsRuntime

Runtime environment based on OpenJDK for running IntelliJ Platform-based products on Windows, macOS, and Linux
GNU General Public License v2.0
1.34k stars 198 forks source link

InternalError when using mockito 5.3 with -XX:+AllowEnhancedClassRedefinition #259

Closed schmidti159 closed 9 months ago

schmidti159 commented 11 months ago

Hi, we recently upgraded from Spring Boot 2.7 to Spring Boot 3.1 and with this we also upgraded mockito from 4.5.1 to 5.3.1 and bytebuddy from 1.12.23 to 1.14.10.

We use JBR in our development flow with -XX:+AllowEnhancedClassRedefinition to have faster development cycles when working on UI tests so no restart is required.

After the upgrade we see exceptions caused by java.lang.InternalError in our tests when we use JBR with this flag.

I uploaded a minimal reproducer here: https://github.com/schmidti159/reproducer_for-internal_error_in_jbr_with_mockito

The readme also contains the complete stacktrace and steps how to reproduce.

I am using IntelliJ IDEA 2023.2.5 to start the test and could reproduce it with JBR version 17.0.9+7-b1087.3

Could you please have a look? Having enhanced class redefinition is very valuable to our development workflow.

mkartashev commented 11 months ago

Thanks for reporting this, I filed JBR-6363 in our issue tracker.

skybber commented 11 months ago

This problem is a bit more difficult. The sample program uses PowerMock, which redefines java.lang.Object, which results in redefining all subclasses, i.e. almost all the classes just loaded in ClassLoader. In this case, there are ~4,000 classes. The size wouldn't be such a problem, but the problem is that it redefines java.lang.Object, which has a lot of bindings and dependencies in the JVM and the current DCEVM doesn't support redefinition of this class. However, a fix is being worked on, but it won't be in the short term, this is a major intervention in the DCEVM code.

schmidti159 commented 10 months ago

Thank you for your analysis. I was not aware that the sample was using PowerMock explicitly, so I looked at it again. The root cause of why it only occurred now, is that Mockito changed the default MockMaker with version 5. Before it was using the subclass MockMaker, now the default is the inline MockMaker (see https://github.com/mockito/mockito/releases/tag/v5.0.0).

So if the subclass MockMaker is enough for the current project a simple workaround is to add this dependency to the project:

    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-subclass</artifactId>
      <scope>test</scope>
    </dependency>
skybber commented 9 months ago

There is a jbr branch with the patch available at:

https://github.com/JetBrains/JetBrainsRuntime/tree/vladimir.dvorak/JBR-6363

if you know how to build a JDK, it would be great if you could try it on your case, but don't feel it's necessary

skybber commented 9 months ago

New release https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-17.0.10b1186.1 support redefinition of java.lang.object, so this issue should be fixed now