-
Bug
-
Resolution: Fixed
-
P4
-
repo-shenandoah
I stumbled upon the following issue when working on JDK-8314599.
SPECjbb run with -XX:ShenandoahOldEvacRatioPercent=100 fails with the following error:
```
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGFPE (0x8) at pc=0x00007f8c7cadc130, pid=46666, tid=46720
#
# JRE version: OpenJDK Runtime Environment (22.0) (build 22-internal-adhoc.ysr.shenandoah)
# Java VM: OpenJDK 64-Bit Server VM (22-internal-adhoc.ysr.shenandoah, mixed mode, tiered, compressed oops, compressed class ptrs, shenandoah gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0xe0e130] ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap*, bool*, ShenandoahCollectionSet*, unsigned long&)+0x130
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
#
--------------- S U M M A R Y ------------
Command Line: -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-ShenandoahPacing -Xmx30g -Xms30g -XX:+AlwaysPreTouch -Xlog:async -Xlog:gc*=info,gc+age=trace,gc+phases=debug -XX:+DisableExplicitGC -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:ShenandoahOldEvacRatioPercent=100 ../specjbb2015.jar -m COMPOSITE
Host: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz, 40 cores, 157G, Amazon Linux release 2 (Karoo)
Time: Tue Dec 12 07:32:43 2023 UTC elapsed time: 6.132387 seconds (0d 0h 0m 6s)
--------------- T H R E A D ---------------
Current thread (0x00007f8c7421fbb0): VMThread "VM Thread" [id=46720, stack(0x00007f8b8797a000,0x00007f8b87a7a000) (1024K)]
Stack: [0x00007f8b8797a000,0x00007f8b87a7a000], sp=0x00007f8b87a77470, free space=1013k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xe0e130] ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap*, bool*, ShenandoahCollectionSet*, unsigned long&)+0x130 (shenandoahGeneration.cpp:284)
V [libjvm.so+0xe0f05c] ShenandoahGeneration::prepare_regions_and_collection_set(bool)+0x18c (shenandoahGeneration.cpp:726)
V [libjvm.so+0xde979f] ShenandoahConcurrentGC::op_final_mark()+0x8f (shenandoahConcurrentGC.cpp:744)
V [libjvm.so+0xdec9bf] ShenandoahConcurrentGC::entry_final_mark()+0x9f (shenandoahConcurrentGC.cpp:350)
V [libjvm.so+0xe93efd] VM_ShenandoahFinalMarkStartEvac::doit()+0x2d (shenandoahVMOperations.cpp:59)
V [libjvm.so+0x103fa21] VM_Operation::evaluate()+0x101 (vmOperations.cpp:73)
V [libjvm.so+0x1042cf2] VMThread::evaluate_operation(VM_Operation*)+0xb2 (vmThread.cpp:281)
V [libjvm.so+0x10439f7] VMThread::inner_execute(VM_Operation*)+0x357 (vmThread.cpp:435)
V [libjvm.so+0x1043cf7] VMThread::run()+0xb7 (vmThread.cpp:502)
V [libjvm.so+0xfb1a38] Thread::call_run()+0xa8 (thread.cpp:220)
V [libjvm.so+0xcef4ea] thread_native_entry(Thread*)+0xda (os_linux.cpp:787)
```
The issue is that although the option's legal range is [0,100], the following code in shenandoahGeneration.cpp::ShenandoahGeneration::compute_evacuation_budgets is problematic when the option value is 100:
- // maximum_old_evacuation_reserve is an upper bound on memory evacuated from old and evacuated to old (promoted).
- size_t maximum_old_evacuation_reserve =
- maximum_young_evacuation_reserve * ShenandoahOldEvacRatioPercent / (100 - ShenandoahOldEvacRatioPercent);
- // Here's the algebra:
- // TotalEvacuation = OldEvacuation + YoungEvacuation
- // OldEvacuation = TotalEvacuation * (ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * (ShenandoahOldEvacRatioPercent/100)/(1 - ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * ShenandoahOldEvacRatioPercent/(100 - ShenandoahOldEvacRatioPercent)
-
A similar flaw exists also in shenandoahHeap.cpp::ShenandoahHeap::adjust_generation_sizes_for_next_cycle:
- // We can limit the reserve to the size of anticipated promotions
- size_t max_old_reserve = young_reserve * ShenandoahOldEvacRatioPercent / (100 - ShenandoahOldEvacRatioPercent);
- // Here's the algebra:
- // TotalEvacuation = OldEvacuation + YoungEvacuation
- // OldEvacuation = TotalEvacuation*(ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * (ShenandoahOldEvacRatioPercent/100)/(1 - ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * ShenandoahOldEvacRatioPercent/(100 - ShenandoahOldEvacRatioPercent)
-
SPECjbb run with -XX:ShenandoahOldEvacRatioPercent=100 fails with the following error:
```
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGFPE (0x8) at pc=0x00007f8c7cadc130, pid=46666, tid=46720
#
# JRE version: OpenJDK Runtime Environment (22.0) (build 22-internal-adhoc.ysr.shenandoah)
# Java VM: OpenJDK 64-Bit Server VM (22-internal-adhoc.ysr.shenandoah, mixed mode, tiered, compressed oops, compressed class ptrs, shenandoah gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0xe0e130] ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap*, bool*, ShenandoahCollectionSet*, unsigned long&)+0x130
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
#
--------------- S U M M A R Y ------------
Command Line: -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-ShenandoahPacing -Xmx30g -Xms30g -XX:+AlwaysPreTouch -Xlog:async -Xlog:gc*=info,gc+age=trace,gc+phases=debug -XX:+DisableExplicitGC -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:ShenandoahOldEvacRatioPercent=100 ../specjbb2015.jar -m COMPOSITE
Host: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz, 40 cores, 157G, Amazon Linux release 2 (Karoo)
Time: Tue Dec 12 07:32:43 2023 UTC elapsed time: 6.132387 seconds (0d 0h 0m 6s)
--------------- T H R E A D ---------------
Current thread (0x00007f8c7421fbb0): VMThread "VM Thread" [id=46720, stack(0x00007f8b8797a000,0x00007f8b87a7a000) (1024K)]
Stack: [0x00007f8b8797a000,0x00007f8b87a7a000], sp=0x00007f8b87a77470, free space=1013k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xe0e130] ShenandoahGeneration::compute_evacuation_budgets(ShenandoahHeap*, bool*, ShenandoahCollectionSet*, unsigned long&)+0x130 (shenandoahGeneration.cpp:284)
V [libjvm.so+0xe0f05c] ShenandoahGeneration::prepare_regions_and_collection_set(bool)+0x18c (shenandoahGeneration.cpp:726)
V [libjvm.so+0xde979f] ShenandoahConcurrentGC::op_final_mark()+0x8f (shenandoahConcurrentGC.cpp:744)
V [libjvm.so+0xdec9bf] ShenandoahConcurrentGC::entry_final_mark()+0x9f (shenandoahConcurrentGC.cpp:350)
V [libjvm.so+0xe93efd] VM_ShenandoahFinalMarkStartEvac::doit()+0x2d (shenandoahVMOperations.cpp:59)
V [libjvm.so+0x103fa21] VM_Operation::evaluate()+0x101 (vmOperations.cpp:73)
V [libjvm.so+0x1042cf2] VMThread::evaluate_operation(VM_Operation*)+0xb2 (vmThread.cpp:281)
V [libjvm.so+0x10439f7] VMThread::inner_execute(VM_Operation*)+0x357 (vmThread.cpp:435)
V [libjvm.so+0x1043cf7] VMThread::run()+0xb7 (vmThread.cpp:502)
V [libjvm.so+0xfb1a38] Thread::call_run()+0xa8 (thread.cpp:220)
V [libjvm.so+0xcef4ea] thread_native_entry(Thread*)+0xda (os_linux.cpp:787)
```
The issue is that although the option's legal range is [0,100], the following code in shenandoahGeneration.cpp::ShenandoahGeneration::compute_evacuation_budgets is problematic when the option value is 100:
- // maximum_old_evacuation_reserve is an upper bound on memory evacuated from old and evacuated to old (promoted).
- size_t maximum_old_evacuation_reserve =
- maximum_young_evacuation_reserve * ShenandoahOldEvacRatioPercent / (100 - ShenandoahOldEvacRatioPercent);
- // Here's the algebra:
- // TotalEvacuation = OldEvacuation + YoungEvacuation
- // OldEvacuation = TotalEvacuation * (ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * (ShenandoahOldEvacRatioPercent/100)/(1 - ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * ShenandoahOldEvacRatioPercent/(100 - ShenandoahOldEvacRatioPercent)
-
A similar flaw exists also in shenandoahHeap.cpp::ShenandoahHeap::adjust_generation_sizes_for_next_cycle:
- // We can limit the reserve to the size of anticipated promotions
- size_t max_old_reserve = young_reserve * ShenandoahOldEvacRatioPercent / (100 - ShenandoahOldEvacRatioPercent);
- // Here's the algebra:
- // TotalEvacuation = OldEvacuation + YoungEvacuation
- // OldEvacuation = TotalEvacuation*(ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * (ShenandoahOldEvacRatioPercent/100)/(1 - ShenandoahOldEvacRatioPercent/100)
- // OldEvacuation = YoungEvacuation * ShenandoahOldEvacRatioPercent/(100 - ShenandoahOldEvacRatioPercent)
-
- is blocked by
-
JDK-8322150 [GenShen] TestPeriodicGC fails with "Generational mode: Should have periodic young GC in logs"
-
- Closed
-
- relates to
-
JDK-8314599 [GenShen] Couple adaptive tenuring and generation size budgeting
-
- Open
-
- links to