Note: I'm only filing this CR for documentation purposes. There are no plans to fix and it can probably be immediately closed.
Regarding FrameIDs, the JDWP spec says:
"Uniquely identifies a frame in the target VM. The frameID must uniquely identify the frame within the entire VM (not only within a given thread). The frameID need only be valid during the time its thread is suspended."
In the current implementation this requirement is not satisfied. It is possible to get away with using a FrameID generated for a frame on one thread to access a frame on another thread.
In the debug agent, the FrameID is composed of two parts:
/* ------------------------------------------------------------ */
/* | thread frame generation (48 bits)| frame number (16 bits)| */
/* ------------------------------------------------------------ */
"frame number" is just the stack depth of the frame. "thread frame generation" comes from ThreadNode.freameGeneration". It starts at 0 and is incremented each time the thread is resumed. This incrementing is meant to invalidate any FrameID that was just created while the thread was suspended. However, there is nothing in frameGeneration that uniquely identifies a thread. It always starts at 0. This means you can get the same FrameID for two different threads, or you can use the FrameID generated for a frame on one thread to access a frame on another thread that has never had a FrameID generated for it.
In order for this to work correctly, frameGeneration needs to include a thread identifier. We could just maintain a counter of threads created, use the current counter as a thread identifier when a ThreadNode is created, and include it in frameGeneration. For example, maybe use 32 of the 48 bits for the thread identifier. frameGeneration would be initialize as follows:
node->frameGeneration = threadID << 32;
And then we can increment it by one each time the thread is resumed just like we currently do. This way two different threads can't end up generating the same FrameID. The downside of this approach is that we eventually start reusing ThreadIDs once the debug agent sees 2^32 of them (4G, which is probably plenty) or 2^16 resumes (64k, which is probably too low). Currently we don't have this reuse issue until there are 2^48 resumes. We can play around we how many bits are allocated for each, but the reality is this approach makes FrameID recycling a reality when before it was not.
For the most part misuse of FrameIDs is protected by JDI. It encapsulates a JDWP FrameID in the StackFrameImpl class, which also holds the ThreadReference, so there is no way to get JDI to use a FrameID created for one thread with a different thread. So with the current JDI implementation, FrameID resuse (recycling) only happens after 2^48 resumes on a thread. For this reason, I'm not recommending that we try to fix this CR.
Regarding FrameIDs, the JDWP spec says:
"Uniquely identifies a frame in the target VM. The frameID must uniquely identify the frame within the entire VM (not only within a given thread). The frameID need only be valid during the time its thread is suspended."
In the current implementation this requirement is not satisfied. It is possible to get away with using a FrameID generated for a frame on one thread to access a frame on another thread.
In the debug agent, the FrameID is composed of two parts:
/* ------------------------------------------------------------ */
/* | thread frame generation (48 bits)| frame number (16 bits)| */
/* ------------------------------------------------------------ */
"frame number" is just the stack depth of the frame. "thread frame generation" comes from ThreadNode.freameGeneration". It starts at 0 and is incremented each time the thread is resumed. This incrementing is meant to invalidate any FrameID that was just created while the thread was suspended. However, there is nothing in frameGeneration that uniquely identifies a thread. It always starts at 0. This means you can get the same FrameID for two different threads, or you can use the FrameID generated for a frame on one thread to access a frame on another thread that has never had a FrameID generated for it.
In order for this to work correctly, frameGeneration needs to include a thread identifier. We could just maintain a counter of threads created, use the current counter as a thread identifier when a ThreadNode is created, and include it in frameGeneration. For example, maybe use 32 of the 48 bits for the thread identifier. frameGeneration would be initialize as follows:
node->frameGeneration = threadID << 32;
And then we can increment it by one each time the thread is resumed just like we currently do. This way two different threads can't end up generating the same FrameID. The downside of this approach is that we eventually start reusing ThreadIDs once the debug agent sees 2^32 of them (4G, which is probably plenty) or 2^16 resumes (64k, which is probably too low). Currently we don't have this reuse issue until there are 2^48 resumes. We can play around we how many bits are allocated for each, but the reality is this approach makes FrameID recycling a reality when before it was not.
For the most part misuse of FrameIDs is protected by JDI. It encapsulates a JDWP FrameID in the StackFrameImpl class, which also holds the ThreadReference, so there is no way to get JDI to use a FrameID created for one thread with a different thread. So with the current JDI implementation, FrameID resuse (recycling) only happens after 2^48 resumes on a thread. For this reason, I'm not recommending that we try to fix this CR.