-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Hibernate Reactive: NamedQuery fails after hot reload #15164
Comments
/cc @DavideD, @Sanne, @gavinking |
I tried your example and I can reproduce the issue when a structural change is made to a class (or some new class is added). |
Just tested setting that in both application.properties and as system property. Unfortunately it didn't seem to have any effect, issue still exists. |
So this does indeed look like a Hibernate (Reactive) issue and not strictly a Quarkus issue |
I think this might also be related to hibernate/hibernate-reactive#537, what do you think? @Sanne, @gavinking |
Yeah I suspect one of the class is still loaded with the previous classloader. That would explain why you need as structural change to trigger it as the new instrumentation mode doesn’t change the class loader. |
@gsmet, I checked in a heap dump and you are of course right - the problematic entity class is present twice, with each instance of the class being loaded with a different classloader. So seems like something in SmallRye Health leads to the old classloader leaking. Now from my point of view, the question is: Would it make more sense to
|
@DavideD any chance you could have a look to this one? |
I will have a look
…On Tue, Mar 2, 2021 at 10:41 PM Guillaume Smet ***@***.***> wrote:
@DavideD <https://github.com/DavideD> any chance you could have a look to
this one?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#15164 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEIQ5ORHNV5K4SIR2H346DTBVSSLANCNFSM4X2AQFAA>
.
|
Well while it's true that we might be able to workaround things in Hibernate, if SmallRye Health is leaking classloaders that needs to be fixed at higher priority. |
When I try to run the reproducer, I have this error:
|
I've added the dependency to the a quickstart and I can recreate the exception |
I gave a look at this issue and I'm not sure exactly what we can do about it from the Hibernate Reactive side. The code we are using is similar to Hibernate ORM and the cause of the problem seems to be this variable in EntityType:
In ORM this variable is lazily initialised and during the hot reload, it gets set to null. When reading it the second time for the check, Hibernate ORM needs to re-initialise it and therefore, everything works. For some reasons, this doesn't happen when using Hibernate Reactive. The variable still reference the old type and therefore keeps track of the old classloader. I suppose we could read the |
@DavideD Thanks a lot for investigating! I was under the assumption that SmallRye Health must be responsible for the leak because the exception isn't thrown when you remove the dependency to |
The error only happens if I add the dependency to the classpath. |
By the way, Hibernate Reactive is still using the same class |
I think I was wrong about this... let me check again |
Argh... it seems it happens even without the dependency. Changing |
Still...not sure what Hibernate Reactive should do differently |
Thanks once again for checking. I tried the reproducer project again and it seems like you are right, removing the dependency to What still does affect the behavior is removing the I also tried the quickstart you mentioned and can confirm that the issue is also reproducible there. Similarly, if you remove the I had another look at some heap dumps, and actually noticed that the |
I did some more debugging. I found out that Hibernate will always try to look up the entity class at When trying to look up the class, Hibernate will use I still have no clue why it just magically works when During debugging, I noticed that the Vert.x eventloop threads are not recreated in dev mode when a hot reload (with new classloader) is performed. Therefore, the old threads are still used which still reference the old TL;DR: Instead of trying to understand what exactly differs in good case and bad case, change Quarkus dev mode to create new eventloop threads when a structural change (with new classloader) is performed. |
That will likely cause massive problems. |
Okay, so if we can't recreate the threads in dev mode during hot reload, what about at least resetting the TCCL of all Vert.x threads on reload? I don't think the approach you mentioned of temporarily setting the TCCL will help us here, because the TCCL is wrong to begin with after hot reload, since it is still pointing to an old classloader that shouldn't be used anymore. Can you maybe point me to the part of the code where the new classloader is created during reload? Then maybe I could try and test a possible solution. |
It's not wrong the first time is it? |
No, at first application start it's correct of course. But after the reload the TCCL still seems to point to the old classloaders, which leads to these issues with Hibernate (and potentially other issues?). |
But that is exactly the issue that the code above works around, isn't it? |
Yes, but I'd argue that in the case of this issue, you can't easily set the TCCL just for that use case and then reset it afterwards as it is done in your examples, because
Therefore I think it might be easier to actually change the TCCL of all the threads in dev mode when the application is reloaded. I'm of course not an expert on the architecture of Quarkus, so that's just what I think would be the most sensible option from an outsider's perspective. I would be happy to be proven wrong 😄 Just trying to move this issue forward. |
That's understandable, but the potential impact of such a change is pretty big. I'd like to avoid that. |
Also, I wanted to clarify that we can't fix the issue in Quarkus itself. |
@geoand Wow, that's funny. You actually just fixed this issue with #15779 😄 I had a look at your changes in that PR and got suspicious because here the behavior was similar, because it only failed if some static resource was present in I guess that wasn't your intention (or maybe it was? 😉), but thanks a lot! |
I'm glad it worked! To be honest, I was kinda hoping it would fix this issue as well, but I had no idea :) |
Describe the bug
Same issue as already described by @cescoffier in #13355, but I was actually able to reproduce it reliably 😄
After the application is reloaded in dev mode due to a code change, named queries do not work anymore. You don't even need to change something in the queried entity itself, just any change that leads to an entire reload of the application will be sufficient.
Expected behavior
NamedQuery should work just as before hot reload.
Actual behavior
Executing a NamedQuery leads to the following exception:
To Reproduce
Link to a small reproducer (preferably a Maven project if the issue is not Gradle-specific).
https://github.com/markusdlugi/hibernate-reactive-hot-swap
Steps to reproduce the behavior:
infrastructure/docker-compose.yml
mvn quarkus:dev
GET http://localhost:8080/fruits
- should still work with HTTP 200com.example.FruitDao
GET http://localhost:8080/fruits
again - application will reload in the background and fail with exceptionConfiguration
Screenshots
(If applicable, add screenshots to help explain your problem.)
Environment (please complete the following information):
uname -a
orver
: Microsoft Windows [Version 10.0.17763.1757]java -version
: OpenJDK 64-Bit Server VM Corretto-11.0.10.9.1 (build 11.0.10+9-LTS, mixed mode)mvnw --version
orgradlew --version
): Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)Additional context
For some reason, the issue only appears if both of the following conditions are met:
io.quarkus:quarkus-smallrye-health
If either of these is removed, the issue just disappears. No idea why.
I don't think that these are the only conditions where this issue appears, most likely this can also happen under different circumstances, but those were the conditions where it failed in our application.
The text was updated successfully, but these errors were encountered: