When calling prototype Beans the first time in a multithreaded manner, the following exception can happen:

Exception in thread "Thread-2" java.lang.ClassCastException: class java.lang.Class cannot be cast to class java.lang.String (java.lang.Class and java.lang.String are in module java.base of loader 'bootstrap')
        at org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClassName(AbstractBeanDefinition.java:393)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1535)
        at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1502)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:492)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:344)
       ...

If this happens, the context/runtime will never raise this exception again. So it seems to be an issue only on startup. This seems to happen since Spring Boot 3. There is nothing to find on google. We assume this error to be unknown so far.

To simplify things and for reproduction, we created a repository that can demonstrate the behaviour: Git Demo Repo for this issue

Please elaborate. Thanks in advance

Comment From: wilkinsona

AbstractBeanDefinition is part of Spring Framework. We'll transfer this issue so that they can investigate.

Comment From: quaff

Reproduced with my local environment.

Comment From: wilkinsona

Thanks for trying it, @quaff. Looking at the code in AbstractBeanDefinition I can see that getBeanClassName isn't thread-safe, but I couldn't reproduce it with the sample even after experimenting with different numbers of threads.

@quaff, @mathekcbo, what OS, JVM, and so on did you use and how many iterations were required before the failure occurred?

Comment From: jhoeller

This is a side effect of f64cc08b6210f67924185e65643d600e5bfb968e where we tried to apply instanceof pattern matching on our new JDK 17 baseline across the codebase, and accidentally lost the defensive access to the beanClass field that we had in 5.3.x there. I'll restore this for 6.0.11, with pattern matching but on a defensive copy of the field still.

Comment From: mase-ppi

Thanks for trying it, @quaff. Looking at the code in AbstractBeanDefinition I can see that getBeanClassName isn't thread-safe, but I couldn't reproduce it with the sample even after experimenting with different numbers of threads.

@quaff, @mathekcbo, what OS, JVM, and so on did you use and how many iterations were required before the failure occurred?

OS: Windows and Linux JVM: JDK 17 Temurin Reproduction: It may occur after some seconds (in the shell loop) or after 15 minutes. It differs

Comment From: jhoeller

This should be restored for the upcoming 6.0.11 snapshot now, in sync with the original behavior in the 5.3.x line.

Comment From: mase-ppi

Thank you for this quick response!