JDK-8163294 : ReservedStack test fails with Framework got StackOverflowError
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • Submitted: 2016-08-05
  • Updated: 2016-08-26
  • Resolved: 2016-08-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Resolved
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
Framework got StackOverflowError at frame = 1227
Test started execution at frame = 971
PASSED

java.lang.LinkageError
	at java.lang.invoke.MethodHandleNatives.linkMethodImpl(java.base@9-internal/MethodHandleNatives.java:386)
	at java.lang.invoke.MethodHandleNatives.linkMethod(java.base@9-internal/MethodHandleNatives.java:366)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetState(java.base@9-internal/AbstractQueuedSynchronizer.java:600)
	at java.util.concurrent.locks.ReentrantLock$Sync.nonfairTryAcquire(java.base@9-internal/ReentrantLock.java:130)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.tryAcquire(java.base@9-internal/ReentrantLock.java:199)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@9-internal/AbstractQueuedSynchronizer.java:1225)
	at java.util.concurrent.locks.ReentrantLock.lock(java.base@9-internal/ReentrantLock.java:267)
	at ReservedStackTest$ReentrantLockTest.lockAndCall(ReservedStackTest.java:169)
	at ReservedStackTest$ReentrantLockTest.lockAndCall(ReservedStackTest.java:170)
	at ReservedStackTest$ReentrantLockTest.lockAndCall(ReservedStackTest.java:170)
...
Caused by: java.lang.StackOverflowError
	at java.util.Arrays.equals(java.base@9-internal/Arrays.java:3186)
	at java.lang.invoke.MethodType.equals(java.base@9-internal/MethodType.java:771)
	at java.lang.invoke.MethodType.equals(java.base@9-internal/MethodType.java:766)
	at java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry.equals(java.base@9-internal/MethodType.java:1314)
	at java.util.concurrent.ConcurrentHashMap.get(java.base@9-internal/ConcurrentHashMap.java:958)
	at java.lang.invoke.MethodType$ConcurrentWeakInternSet.get(java.base@9-internal/MethodType.java:1252)
	at java.lang.invoke.MethodType.makeImpl(java.base@9-internal/MethodType.java:305)
	at java.lang.invoke.MethodType.insertParameterTypes(java.base@9-internal/MethodType.java:403)
	at java.lang.invoke.MethodType.appendParameterTypes(java.base@9-internal/MethodType.java:416)
	at java.lang.invoke.MethodHandleNatives.varHandleOperationLinkerMethod(java.base@9-internal/MethodHandleNatives.java:448)
	at java.lang.invoke.MethodHandleNatives.linkMethodImpl(java.base@9-internal/MethodHandleNatives.java:378)
	at java.lang.invoke.MethodHandleNatives.linkMethod(java.base@9-internal/MethodHandleNatives.java:366)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetState(java.base@9-internal/AbstractQueuedSynchronizer.java:600)
	at java.util.concurrent.locks.ReentrantLock$Sync.nonfairTryAcquire(java.base@9-internal/ReentrantLock.java:130)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.tryAcquire(java.base@9-internal/ReentrantLock.java:199)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@9-internal/AbstractQueuedSynchronizer.java:1225)
	at java.util.concurrent.locks.ReentrantLock.lock(java.base@9-internal/ReentrantLock.java:267)
	at ReservedStackTest$ReentrantLockTest.lockAndCall(ReservedStackTest.java:169)


Comments
Thanks Paul, I was wondering if the test had to be made robust against LinkageError or not. I'll close it as a duplicate of JDK-8163553.
26-08-2016

Fred, i think the test is doing the right thing. I need to fix the error handling of signature polymorphic method linkage to not wrap Errors. Feel free to close this as a duplicate of JDK-8163553.
26-08-2016

Interesting failure, default value for StackReservedPages on Aarch64 is currently 0, which means that the feature is not supported on this platform. If the feature is not supported, the lock robustness test should failed internally, but this failure should be filtered out by the while list of supported platforms, and the result returned by the test should be PASSED. However, the test design was not expecting the lock robustness test to fail with a LinkageError. This Error is not caught, so it propagates up to the top level method and makes the whole test fail. This bug is not a sizing issue with StackReservedPages but a test bug. Incidentally, it shows some issues with the way some Error are handled in VarHandles implementation, which is a good thing anyway.
26-08-2016

This is what I'm currently trying to figure out. So far, Aarch64 seems to be the only platform requiring a DEFAULT_STACK_RESERVED_PAGES increase, but I don't have direct access to a Aarch64 machine to experiment new sizes. I'm still working on setting up a way to test new sizes.
10-08-2016

I can probably reduce the size of the stack a little by making MethodHandleNatives,varHandleOperationLinkerMethod a little more efficient but i think overall MethodHandles/VarHandles linkage requires larger stack sizes so we have to cope with that. Fred, what should we increase DEFAULT_STACK_RESERVED_PAGES to? and on what platforms?
10-08-2016

The LinkageError is due to java.lang.invoke.MethodHandleNatives.linkMethodImpl catching all exceptions and wrapping them in LinkageError - which is not an appropriate thing to do. See JDK-8163553.
10-08-2016

The only idea I have is getting some way to do some of the lazy initialization of VarHandles at class-load time, as we do with eager class-load of LockSupport. But I have no idea if there's a way to do that. I'm dis-owning this bug; perhaps Paul or Frederic want to take over? Long-term I'm still hoping we get growable thread stacks, so we can abandon the brittle ReservedStack mechanism.
09-08-2016

I don't have any clever thoughts about it: VarHandle stack requirements aren't likely to shrink any time soon, and @ReservedStack is a heuristic that needs a good estimate of size to reserve. So it looks like that size will need to be increased.
08-08-2016

Doug, Martin: what are your thoughts on this? The VarHandle changes potentially require much larger stacks.
08-08-2016

The LinkageError is new and unexpected. The lock code is using VarHandle, which was not the case before. The java.util.concurrent code has recently been updated by Doug Lea: JDK-8080603: Replace Unsafe with VarHandle in java.util.concurrent classes. The java.util.concurrent.locks.ReentrantLock$Sync.nonfairTryAcquire() in the call stack in one of the methods annotated with ReservedStackAccess, and it is supposed to have access to more stack space when a stack overflow occurs during its execution, because the completion of its execution is critical to preserve lock state consistency. One of the limitation of the Reserved Stack Area is that its size has to be set statically, and oversizing it results in wasted memory. Before JDK-8080603, compareAndSetState() was simply a call to an Unsafe method implemented in the JVM. Its requirements in term of stack space was small and well defined. After JDK-8080603, compareAndSetState() uses the VarHandle mechanism, which requires a significantly bigger stack space with numerous calls to Java code: at java.util.Arrays.equals(java.base@9-internal/Arrays.java:3186) at java.lang.invoke.MethodType.equals(java.base@9-internal/MethodType.java:771) at java.lang.invoke.MethodType.equals(java.base@9-internal/MethodType.java:766) at java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry.equals(java.base@9-internal/MethodType.java:1314) at java.util.concurrent.ConcurrentHashMap.get(java.base@9-internal/ConcurrentHashMap.java:958) at java.lang.invoke.MethodType$ConcurrentWeakInternSet.get(java.base@9-internal/MethodType.java:1252) at java.lang.invoke.MethodType.makeImpl(java.base@9-internal/MethodType.java:305) at java.lang.invoke.MethodType.insertParameterTypes(java.base@9-internal/MethodType.java:403) at java.lang.invoke.MethodType.appendParameterTypes(java.base@9-internal/MethodType.java:416) at java.lang.invoke.MethodHandleNatives.varHandleOperationLinkerMethod(java.base@9-internal/MethodHandleNatives.java:448) at java.lang.invoke.MethodHandleNatives.linkMethodImpl(java.base@9-internal/MethodHandleNatives.java:378) at java.lang.invoke.MethodHandleNatives.linkMethod(java.base@9-internal/MethodHandleNatives.java:366) at java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetState(java.base@9-internal/AbstractQueuedSynchronizer.java:600) at java.util.concurrent.locks.ReentrantLock$Sync.nonfairTryAcquire(java.base@9-internal/ReentrantLock.java:130) at java.util.concurrent.locks.ReentrantLock$NonfairSync.tryAcquire(java.base@9-internal/ReentrantLock.java:199) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@9-internal/AbstractQueuedSynchronizer.java:1225) at java.util.concurrent.locks.ReentrantLock.lock(java.base@9-internal/ReentrantLock.java:267) at ReservedStackTest$ReentrantLockTest.lockAndCall(ReservedStackTest.java:169) I suspect that this significant increase in stack space requirement makes the current sizing of the Reserved Stack Area insufficient to allow the completion of the nonfairTryAcquire(), leading to an expected, non deferrable stack overflow, which is later transformed into a LinkError. If my analysis of the failure is correct, it doesn't mean that there's a bug in Reserved Stack Area or JDK-8080603. The test failure simply indicates that nonfairTryAcquire() is not protected anymore against stack overflows because the new code requires more stack space than the old one and the size of the reserved area has not been increased accordingly. The way to restore the protection is to increase DEFAULT_STACK_RESERVED_PAGES for this platform.
08-08-2016