RFR (S) 8205608: Fix 'frames()' in ThreadReferenceImpl.c to prevent quadratic runtime behavior

serguei.spitsyn at oracle.com serguei.spitsyn at oracle.com
Fri Jul 20 21:04:22 UTC 2018


On 7/20/18 13:44, Chris Plummer wrote:
> On 7/20/18 1:40 PM, serguei.spitsyn at oracle.com wrote:
>> Hi Ralf,
>>
>>
>> On 7/20/18 07:28, Schmelter, Ralf wrote:
>>> Hi Sergue,
>>>
>>> I’ve updated the webref: 
>>> http://cr.openjdk.java.net/~simonis/webrevs/2018/8205608.v4/
>>
>> The copyright year in ThreadReferenceImpl.c still has to be 2018, not 
>> 2008.
>>
>> http://cr.openjdk.java.net/~simonis/webrevs/2018/8205608.v4/test/jdk/com/sun/jdi/Frames2Test.java.html 
>>
>>
>>   72             if (newDepth == -1_000) {
>>   73                 // Pop some frames so there is room on the stack 
>> for the
>>   74                 // call (including println()).
>>   75                 notifyRecursionEnded();
>>   76             }
>>
>>   I have a concern on potential issue mentioned in the comment above.
>>   Should a StackOverflowError be expected here?
>>
>>   79         } catch (StackOverflowError e) {
>>   80             // Use negative depth to indicate the recursion has 
>> ended.
>>   81             return -1;
>>   82         }
>>
>>   What is going to happen if the StackOverflowError was really caught 
>> above?
> The SOE is really caught in the above code. I returns -1, and starts 
> the unwinding of the stack. After 1000 frames have been popped via 
> returns, notifyRecursionEnded() will be called. The pops are so 
> notifyRecursionEnded() can be called without worry of another SOE.

Got it, thanks Chris.

So, I'm Okay with the fix assuming the copyright year is fixed.

Thanks,
Serguei

>
> Chris
>>   If I understand it correctly, the notifyRecursionEnded() call will 
>> be missed then.
>>   This breakpoint will be missed as well:
>>
>>   107         bpe = resumeTo("Frames2Targ", "notifyRecursionEnded", 
>> "()V");
>>
>>
>>
>>> JVMTI_ERROR_OPAQUE_FRAME was never returned from GetFrameLocation(). 
>>> If it would have, the old code would have removed all native methods 
>>> from the call stack. The original JVMDI call did indeed return 
>>> JVMDI_ERROR_OPAQUE_FRAME, so maybe it was a leftover from the 
>>> JVMDI->JVMTI transition.
>>
>> Agreed.
>>
>>> I’ve tried to make the test more readable and added some comments to 
>>> explain why it is done the way it is.
>>
>> Thank you for the update!
>>
>>
>> Thanks,
>> Serguei
>>
>>> Best regards,
>>> Ralf
>>>
>>>
>>>
>>>
>>> From: serguei.spitsyn at oracle.com [mailto:serguei.spitsyn at oracle.com]
>>> Sent: Mittwoch, 18. Juli 2018 22:57
>>> To: Chris Plummer <chris.plummer at oracle.com>; Schmelter, Ralf 
>>> <ralf.schmelter at sap.com>; serviceability-dev at openjdk.java.net; 
>>> Stuefe, Thomas <thomas.stuefe at sap.com>
>>> Subject: Re: RFR (S) 8205608: Fix 'frames()' in 
>>> ThreadReferenceImpl.c to prevent quadratic runtime behavior
>>>
>>> Hi Ralf,
>>>
>>> The fix itself looks pretty good to me.
>>> Some minor comments.
>>>
>>> The copyright year needs an update.
>>>   218     jint count, filledIn;
>>>
>>>   Could you, please, split the declarations above into different 
>>> lines to follow the local style?
>>> Ii is interesting that the original implementation checked the error 
>>> code returned
>>> from the JVMTI GetFrameLocation for being equal to 
>>> JVMTI_ERROR_OPAQUE_FRAME.
>>> However, the GetFrameLocation spec does not list this error code as 
>>> possible.
>>>
>>>
>>> Some comments about the test.
>>>    52     static void callEnded() {
>>>    53         System.out.println("SOE occurred as expected");
>>>    54     }
>>>    55
>>>    56     static int call(int depth) {
>>>    57         if (depth == 0) {
>>>    58             // Should have seen a stack overflow by now.
>>>    59             System.out.println("Exited without creating SOE");
>>>    60             System.exit(0);
>>>    61         }
>>>    62
>>>    63         try {
>>>    64             int newDepth = call(depth - 1);
>>>    65
>>>    66             if (newDepth == -1_000) {
>>>    67                 // Pop some frames so there is room on the 
>>> stack for the
>>>    68                 // println()
>>>    69                 callEnded();
>>>    70             }
>>>    71
>>>    72             return newDepth - 1;
>>>    73         } catch (StackOverflowError e) {
>>>    74             return -1;
>>>    75         }
>>>    76     }
>>>    77 }
>>>    I'd suggest to rename the methods call() and callEnded() to 
>>> something like
>>>    recursiveMethod() and recursionEnd().
>>>    Also, the manipulations with SOE create a complexity and are 
>>> confusing.
>>>    Could it be more simple to let it propagated and then catch in 
>>> main()?
>>>    What is the point for all these checks at the lines 104-119?
>>>    In general, I'm looking for some ways to make it more clear, 
>>> simple and stable.
>>>
>>> Thanks,
>>> Serguei
>>
>



More information about the serviceability-dev mailing list