-
Notifications
You must be signed in to change notification settings - Fork 375
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
Memory leak in stored exceptions #9960
Comments
This is relevant for me because of exceptions that are permanently stored and repeatedly rethrown from a library code , see javacc/javacc#99 and javacc/javacc#284. (I know that the need to store and rethrow exception means they are no longer exceptional and should be replaced by boolean flags, but such change to JavaCC would require more work than the fix suggested here, which might be useful in other cases as well). |
Can you confirm that this is a leak in the sense of "I was expecting zero instances and I got one, after throwing the same exception three times"? It looks as though each throw loses the previous instances at least, so the objects live as long as the exception's backing object hasn't yet been thrown again? I'm not certain we can nicely clear that out, since it is in the underlying JS exception - if Java rethrows the exception back to JS, that backing object is what is caught in JS. I'm not quite sure why the browser holds on to the instance of the method that was part of the stack trace, it doesn't seem accessible.
Note that this will not work if jsinterop exports are disabled, or if the Throwable type isn't listed in the jsinterop includes. Also, It looks like there is other cleanup that could happen in Throwable as well, If the Or, let the new implementation just rewrite the stack property with itself as a new string? That appears to resolve the leak as well. |
Yes.
Not sure about the why, but we've been using the workaround in GeoGebra for a while now and it works well.
Do you mean this |
I've been thinking about this a bit more, and I am suspecting this is a side effect of Chromium's async stack trace support. Replacing the stack trace (even with itself) is enough to tell it that you control the stack trace, so the debugger need not keep track of the information about higher frames any longer. This would make sense in your case, where you don't expect to use that exception again for its existing trace, but if I'm correct, might break the debugging experience for other users if applied to GWT itself. Given the nature of your code, I would expect in prod mode that the Perhaps worth filing a bug on the Chromium bug tracker to confirm that this apparent leak is required for some reason (such as for async stack debugging), or if it is actually a bug? Another possible workaround could be a patch for javacc (or editing generated code) that calls the super constructor with writableStackTrace set to false? I'm not sure if that would stop the leak, or just stop GWT from trying to translate it. |
Chromium issue https://issues.chromium.org/issues/347649756
Indeed, in prod the method is static and there is no
That's what the minimal example is already doing (https://github.com/zbynek/stacktracer/blob/main/stacktracer-client/src/main/java/com/example/SingletonException.java#L7), but it does not resolve the issue (seems that it only prevents the Java stacktrace setup). Also this flag is only viable for exceptions that extend |
Having looked more closely than I have, would it make sense to resolve this by altering Throwable so that writableStackTrace==false would omit creating the stack trace, or am I misinterpreting what that flag would do in other circumstances? Or, is it a decent workaround to build a app-specific collector that won't apply to SingletonException and its subtypes (via an instanceof check)? |
My idea was to add a flag, let's say we name it If I understand your first suggestion correctly, you're proposing to use |
Apparently the Chromium issue is known since 2017 https://issues.chromium.org/issues/42210375 |
GWT version: 2.11
Browser (with version): Chrome, any recent
Operating System: Windows (probably others)
Description
Storing an exception (e.g. in static final field) that was thrown from an instance method keeps instances of otherwise unused objects in the JS memory heap.
Steps to reproduce
mvn gwt:codeserver -pl *-client -am "-Dgwt.style=DETAILED"
mvn jetty:run -pl *-server -am -Denv=dev
Expected
Ephemeral
not in heapActual
Ephemeral
in heap (detailed namecom_example_Ephemeral_Ephemeral__IV
), referenced assymbol
from thebackingJsObject
of the exceptionKnown workarounds
If the exception is accessible from your code (not coming from library code), use JSInterop to remove the backing object like this:
If the exception comes from code you do not control, the above workaround can be combined with super-sourcing.
Possible fix
It may not be possible to fix this in general, but for exceptions that override
fillInStackTrace
in a way that avoids callingfillInStackTrace
on theThrowable
superclass, GWT could skip initialization ofbackingJsObject
to maintain the Java semantic of "I don't care where this exception came from".The text was updated successfully, but these errors were encountered: