Bug 449791 - Debugger issues multiple classesBySignature requests when classes have been unloaded.
Summary: Debugger issues multiple classesBySignature requests when classes have been u...
Status: ASSIGNED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Debug (show other bugs)
Version: 4.4.1   Edit
Hardware: PC All
: P3 major with 3 votes (vote)
Target Milestone: ---   Edit
Assignee: JDT-Debug-Inbox CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-03 10:37 EST by Duncan MacGregor CLA
Modified: 2024-02-05 16:33 EST (History)
6 users (show)

See Also:


Attachments
Example project which shows the problem. (10.01 KB, application/zip)
2014-11-27 15:10 EST, Duncan MacGregor CLA
no flags Details
Proposed patch. (19.74 KB, patch)
2014-12-08 08:45 EST, Duncan MacGregor CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Duncan MacGregor CLA 2014-11-03 10:37:01 EST
When a class is unloaded from the JVM the debugger receives a class unloaded event and gets the signature of the unloaded class. It then calls VirtualMachineImpl.removeKnownRefType() to try and remove the unloaded class from the cache of known reference types.

To do this it tries to get a reference type ID using the JDWP classesBySignature command, but since the class has been unloaded it will never successfully get the ref type ID for the unloaded class, so will either do nothing to the cache, or potentially remove the wrong class.

This causes a problem on Oracle JDK & OpenJDK 8 with heavy use of invokeDynamic because the LambdaForms used to implement MethodHandles and invokeDynamic can generate a large number of classes, and these may get garbage collected in large numbers. Issuing large numbers of classesBySignature calls (1 per GCed class) is very expensive since the JVM has to iterate over every loaded class to compare the signatures, and can cause applications to freeze for up to 5 minutes.
Comment 1 Herve Girod CLA 2014-11-23 08:49:11 EST
This bug can cause a huge problem when debugging an app using invokeDynamic.
Comment 2 Sarika Sinha CLA 2014-11-27 01:17:03 EST
(In reply to Duncan MacGregor from comment #0)
Can you attach a sample project where you are facing this problem ?
Comment 3 Duncan MacGregor CLA 2014-11-27 15:10:38 EST
Created attachment 248986 [details]
Example project which shows the problem.

I've attached an example project that should demonstrate the problem. Requires the ASM 5 library to link against. Generates a large number of classes and then garbage collects to make them unload. Under normal operation each load of 1000 classes will take approximately the same time, with occasional slight slowdown for garbage collection. Under the debugger long pauses (of up to 2 minutes on my machine) can be observed. To observe significant pauses it is critical that there are both a large number of classes still in memory & that a large number have been unloaded.
Comment 4 Sarika Sinha CLA 2014-11-28 05:37:51 EST
Currently, we cache the value by ID, and to get the Id for signature we are using the JDWP classesBySignature command. Should we use one more cache to store boolean for a signature. If we have stored ids for the signature we can flag that. If all the ids for a signature is unloaded, we need to flag that again. 

So before invoking classesBySignature  we can check in this new cache and then if required invoke classesBySignature.
Comment 5 Duncan MacGregor CLA 2014-11-28 05:53:48 EST
I think you need a cache mapping signatures to (sets of) IDs. when a you discover a signature has been unloaded you then check how many IDs have that signature. If you have IDs against a signature then you need to check the status of each and remove ones which are no longer valid. I would be very cautious about optimising the case where you only have one ID against a signature as that could be an artefact of having just removed a whole bunch of unloaded classes.

I think classesBySignature should never be used in this area as it will not return any IDs for the classes that have been removed, so you'll never remove them from your cache.
Comment 6 Duncan MacGregor CLA 2014-12-03 14:37:43 EST
I've written a quick proof of concept fix for this, but it has the potential to build up a useless map of signatures to expired reference type IDs, so it's not exactly production quality.

I'm going to try turning it into something more robust by introducing a ReferenceTypeCache class which can manage all the internal cleanup neatly, and return all cached reference types for a signature. I don't think any API changes are needed on VirtualMachineImpl as fCachedReftypes is private and isn't returned by any methods. There is a potential performance hit as signatures will have to be fetched for types when they are cached (if they haven't been set already).
Comment 7 Duncan MacGregor CLA 2014-12-08 08:45:23 EST
Created attachment 249237 [details]
Proposed patch.

Okay, this seems to work for me, in my test case there is still a short pause when classes are unloaded but it's much shorter than before. I couldn't find any unit tests that were really focused on this area, and I'm not sure how you guys implement tests for internals
Comment 8 Andrey Loskutov CLA 2019-09-18 02:31:15 EDT
We face same issue in our application.

Sarika, do you plan to follow up on this? 
If not, we (me & Simeon) should take this.
Comment 9 Sarika Sinha CLA 2019-09-18 03:36:43 EDT
(In reply to Andrey Loskutov from comment #8)
> We face same issue in our application.
> 
> Sarika, do you plan to follow up on this? 
> If not, we (me & Simeon) should take this.

I don't plan to work on this right now.
Comment 10 Eclipse Genie CLA 2019-09-18 09:30:56 EDT
New Gerrit change created: https://git.eclipse.org/r/149760
Comment 11 Simeon Andreev CLA 2019-09-18 09:36:17 EDT
I've taken the patch suggested by Duncan MacGregor: https://git.eclipse.org/r/#/c/149760/

I've not examined what the TypeCache does, which is most of the change. But with the case in which we observe classes which can't get unloaded by the JVM due to JDT, the problem is gone with the patch.
Comment 12 Sarika Sinha CLA 2019-11-13 06:41:34 EST
@Simeon 
Do you plan to complete this for 4.14?
Else you can move it to 4.15.
Comment 13 Sarika Sinha CLA 2019-11-22 05:43:38 EST
If you still plan to fix it in 4.14 RC1, please change the target milestone.
Comment 14 Sarika Sinha CLA 2020-02-24 00:32:48 EST
Removed the target, please put the target when planned.
Comment 15 Eclipse Genie CLA 2022-02-14 07:59:48 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 16 Eclipse Genie CLA 2024-02-05 16:33:15 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.