JDK-8214349 : Implementation: JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)
  • Type: CSR
  • Component: hotspot
  • Sub-Component: gc
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 12
  • Submitted: 2018-11-27
  • Updated: 2018-12-06
  • Resolved: 2018-12-06
Related Reports
CSR :  
Description
Summary
-------

Add command line options to enable and configure the Shenandoah GC.

Problem
-------

I would like to add the Shenandoah Garbage Collector. Similar to any other GC, this would have to be enabled by -XX:+UseShenandoahGC on the command line. Also, similar to other GCs, Shenandoah comes with a number of knobs that can change the behaviour of the GC.

Solution
--------

The primary command line flag to be added is -XX:+UseShenandoahGC. This option will be added as an experimental flag to gc_globals.hpp.

Additional command line options would be added to configure Shenandoah's behaviour. They are all prefixed by 'Shenandoah' and reside in shenandoah_globals.hpp.

Specification
-------------

From gc_globals.hpp:

    +  experimental(bool, UseShenandoahGC, false,                                \
    +          "Use the Shenandoah garbage collector")                           \
    +                                                                            \

From shenandoah_globals:

    +  experimental(size_t, ShenandoahHeapRegionSize, 0,                         \
    +          "Size of the Shenandoah regions. Set to zero to detect "          \
    +          "automatically.")                                                 \
    +                                                                            \
    +  experimental(size_t, ShenandoahTargetNumRegions, 2048,                    \
    +          "Target number of regions. We try to get around that many "       \
    +          "regions, based on Shenandoah{Min,Max}RegionSize.")               \
    +                                                                            \
    +  experimental(size_t, ShenandoahMinRegionSize, 256 * K,                    \
    +          "Minimum Shenandoah heap region size.")                           \
    +                                                                            \
    +  experimental(size_t, ShenandoahMaxRegionSize, 32 * M,                     \
    +          "Maximum Shenandoah heap region size.")                           \
    +                                                                            \
    +  experimental(intx, ShenandoahHumongousThreshold, 100,                     \
    +          "How large should the object be to get allocated in humongous "   \
    +          "region, in percents of heap region size. This also caps the "    \
    +          "maximum TLAB size.")                                             \
    +          range(1, 100)                                                     \
    +                                                                            \
    +  experimental(ccstr, ShenandoahGCHeuristics, "adaptive",                   \
    +          "The heuristics to use in Shenandoah GC. Possible values:"        \
    +          " *) adaptive - adapt to maintain the given amount of free heap;" \
    +          " *) static  -  start concurrent GC when static free heap "       \
    +          "               threshold and static allocation threshold are "   \
    +          "               tripped;"                                         \
    +          " *) passive -  do not start concurrent GC, wait for Full GC; "   \
    +          " *) aggressive - run concurrent GC continuously, evacuate "      \
    +          "               everything;"                                      \
    +          " *) compact - run GC with lower footprint target, may end up "   \
    +          "               doing continuous GC, evacuate lots of live "      \
    +          "               objects, uncommit heap aggressively;")            \
    +                                                                            \
    +  experimental(ccstr, ShenandoahUpdateRefsEarly, "adaptive",                \
    +          "Run a separate concurrent reference updating phase after"        \
    +          "concurrent evacuation. Possible values: 'on', 'off', 'adaptive'")\
    +                                                                            \
    +  experimental(uintx, ShenandoahRefProcFrequency, 5,                        \
    +          "How often should (weak, soft, etc) references be processed. "    \
    +          "References get processed at every Nth GC cycle. Set to zero "    \
    +          "to disable reference processing.")                               \
    +                                                                            \
    +  experimental(uintx, ShenandoahUnloadClassesFrequency, 5,                  \
    +          "How often should classes get unloaded. "                         \
    +          "Class unloading is performed at every Nth GC cycle. "            \
    +          "Set to zero to disable class unloading during concurrent GC.")   \
    +                                                                            \
    +  experimental(uintx, ShenandoahGarbageThreshold, 60,                       \
    +          "Sets the percentage of garbage a region need to contain before " \
    +          "it can be marked for collection. Does not apply to all "         \
    +          "heuristics.")                                                    \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahFreeThreshold, 10,                          \
    +          "Set the percentage of free heap at which a GC cycle is started. "\
    +          "Does not apply to all heuristics.")                              \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahInitFreeThreshold, 70,                      \
    +          "Initial remaining free heap threshold for learning steps in "    \
    +          "heuristics. In percents of total heap size. Does not apply to "  \
    +          "all heuristics.")                                                \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahMinFreeThreshold, 10,                       \
    +          "Minimum remaining free space threshold, after which collection " \
    +          "definitely triggers. Does not apply to all heuristics.")         \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahAllocationThreshold, 0,                     \
    +          "Set percentage of memory allocated since last GC cycle before "  \
    +          "a new GC cycle can be started. Set to zero to effectively "      \
    +          "disable.")                                                       \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahLearningSteps, 5,                           \
    +          "Number of GC cycles to run in order to learn application "       \
    +          "and GC performance for adaptive heuristics.")                    \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahImmediateThreshold, 90,                     \
    +          "If mark identifies more than this much immediate garbage "       \
    +          "regions, it shall recycle them, and shall not continue the "     \
    +          "rest of the GC cycle. The value is in percents of total "        \
    +          "number of candidate regions for collection set. Setting this "   \
    +          "threshold to 100% effectively disables this shortcut.")          \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahMergeUpdateRefsMinGap, 100,                 \
    +          "If GC is currently running in separate update-refs mode "        \
    +          "this numbers gives the threshold when to switch to "             \
    +          "merged update-refs mode. Number is percentage relative to"       \
    +          "duration(marking)+duration(update-refs).")                       \
    +                                                                            \
    +  experimental(uintx, ShenandoahMergeUpdateRefsMaxGap, 200,                 \
    +          "If GC is currently running in merged update-refs mode "          \
    +          "this numbers gives the threshold when to switch to "             \
    +          "separate update-refs mode. Number is percentage relative "       \
    +          "to duration(marking)+duration(update-refs).")                    \
    +                                                                            \
    +  experimental(uintx, ShenandoahGuaranteedGCInterval, 5*60*1000,            \
    +          "Adaptive and dynamic heuristics would guarantee a GC cycle "     \
    +          "at least with this interval. This is useful when large idle"     \
    +          " intervals are present, where GC can run without stealing "      \
    +          "time from active application. Time is in milliseconds.")         \
    +                                                                            \
    +  experimental(bool, ShenandoahAlwaysClearSoftRefs, false,                  \
    +          "Clear soft references always, instead of using any smart "       \
    +          "cleanup policy. This minimizes footprint at expense of more "    \
    +          "softref churn in applications.")                                 \
    +                                                                            \
    +  experimental(bool, ShenandoahUncommit, true,                              \
    +          "Allow Shenandoah to uncommit unused memory.")                    \
    +                                                                            \
    +  experimental(uintx, ShenandoahUncommitDelay, 5*60*1000,                   \
    +          "Shenandoah would start to uncommit memory for regions that were" \
    +          " not used for more than this time. First use after that would "  \
    +          "incur allocation stalls. Actively used regions would never be "  \
    +          "uncommitted, because they never decay. Time is in milliseconds." \
    +          "Setting this delay to 0 effectively makes Shenandoah to "        \
    +          "uncommit the regions almost immediately.")                       \
    +                                                                            \
    +  experimental(bool, ShenandoahRegionSampling, false,                       \
    +          "Turns on heap region sampling via JVMStat")                      \
    +                                                                            \
    +  experimental(int, ShenandoahRegionSamplingRate, 40,                       \
    +          "Sampling rate for heap region sampling. "                        \
    +          "Number of milliseconds between samples")                         \
    +                                                                            \
    +  experimental(uintx, ShenandoahControlIntervalMin, 1,                      \
    +          "The minumum sleep interval for control loop that drives "        \
    +          "the cycles. Lower values would increase GC responsiveness "      \
    +          "to changing heap conditions, at the expense of higher perf "     \
    +          "overhead. Time is in milliseconds.")                             \
    +                                                                            \
    +  experimental(uintx, ShenandoahControlIntervalMax, 10,                     \
    +          "The maximum sleep interval for control loop that drives "        \
    +          "the cycles. Lower values would increase GC responsiveness "      \
    +          "to changing heap conditions, at the expense of higher perf "     \
    +          "overhead. Time is in milliseconds.")                             \
    +                                                                            \
    +  experimental(uintx, ShenandoahControlIntervalAdjustPeriod, 1000,          \
    +          "The time period for one step in control loop interval "          \
    +          "adjustment. Lower values make adjustments faster, at the "       \
    +          "expense of higher perf overhead. Time is in milliseconds.")      \
    +                                                                            \
    +  diagnostic(bool, ShenandoahVerify, false,                                 \
    +          "Verify the Shenandoah garbage collector")                        \
    +                                                                            \
    +  diagnostic(intx, ShenandoahVerifyLevel, 4,                                \
    +          "Shenandoah verification level: "                                 \
    +          "0 = basic heap checks; "                                         \
    +          "1 = previous level, plus basic region checks; "                  \
    +          "2 = previous level, plus all roots; "                            \
    +          "3 = previous level, plus all reachable objects; "                \
    +          "4 = previous level, plus all marked objects")                    \
    +                                                                            \
    +  diagnostic(bool, ShenandoahElasticTLAB, true,                             \
    +          "Use Elastic TLABs with Shenandoah")                              \
    +                                                                            \
    +  diagnostic(bool, ShenandoahAllowMixedAllocs, true,                        \
    +          "Allow mixing mutator and collector allocations in a single "     \
    +          "region")                                                         \
    +                                                                            \
    +  experimental(uintx, ShenandoahAllocSpikeFactor, 5,                        \
    +          "The amount of heap space to reserve for absorbing the "          \
    +          "allocation spikes. Larger value wastes more memory in "          \
    +          "non-emergency cases, but provides more safety in emergency "     \
    +          "cases. In percents of total heap size.")                         \
    +          range(0,100)                                                      \
    +                                                                            \
    +  experimental(uintx, ShenandoahEvacReserve, 5,                             \
    +          "Maximum amount of free space to reserve for evacuation. "        \
    +          "Larger values make GC more aggressive, while leaving less "      \
    +          "headroom for application to allocate in. "                       \
    +          "In percents of total heap size.")                                \
    +          range(1,100)                                                      \
    +                                                                            \
    +  experimental(double, ShenandoahEvacWaste, 1.2,                            \
    +          "How much waste evacuations produce within the reserved "         \
    +          "space. Larger values make evacuations more resilient "           \
    +          "against allocation failures, at expense of smaller csets "       \
    +          "on each cycle.")                                                 \
    +          range(1.0,100.0)                                                  \
    +                                                                            \
    +  experimental(bool, ShenandoahEvacReserveOverflow, true,                   \
    +          "Allow evacuations to overflow the reserved space. "              \
    +          "Enabling it will make evacuations more resilient when "          \
    +          "evacuation reserve/waste is incorrect, at the risk that "        \
    +          "application allocations run out of memory too early.")           \
    +                                                                            \
    +  diagnostic(bool, ShenandoahAllocationTrace, false,                        \
    +          "Trace allocation latencies and stalls. Can be expensive when "   \
    +          "lots of allocations happen, and may introduce scalability "      \
    +          "bottlenecks.")                                                   \
    +                                                                            \
    +  diagnostic(intx, ShenandoahAllocationStallThreshold, 10000,               \
    +          "When allocation tracing is enabled, the allocation stalls "      \
    +          "larger than this threshold would be reported as warnings. "      \
    +          "Time is in microseconds.")                                       \
    +                                                                            \
    +  experimental(uintx, ShenandoahEvacAssist, 10,                             \
    +          "How many objects to evacuate on WB assist path. "                \
    +          "Use zero to disable.")                                           \
    +                                                                            \
    +  experimental(bool, ShenandoahPacing, true,                                \
    +          "Pace application allocations to give GC chance to start "        \
    +          "and complete before allocation failure is reached.")             \
    +                                                                            \
    +  experimental(uintx, ShenandoahPacingMaxDelay, 10,                         \
    +          "Max delay for pacing application allocations. "                  \
    +          "Time is in milliseconds.")                                       \
    +                                                                            \
    +  experimental(uintx, ShenandoahPacingIdleSlack, 2,                         \
    +          "Percent of heap counted as non-taxable allocations during idle. "\
    +          "Larger value makes the pacing milder during idle phases, "       \
    +          "requiring less rendezvous with control thread. Lower value "     \
    +          "makes the pacing control less responsive to out-of-cycle allocs.")\
    +          range(0, 100)                                                     \
    +                                                                            \
    +  experimental(uintx, ShenandoahPacingCycleSlack, 10,                       \
    +          "Percent of free space taken as non-taxable allocations during "  \
    +          "the GC cycle. Larger value makes the pacing milder at the "      \
    +          "beginning of the GC cycle. Lower value makes the pacing less "   \
    +          "uniform during the cycle.")                                      \
    +          range(0, 100)                                                     \
    +                                                                            \
    +  experimental(double, ShenandoahPacingSurcharge, 1.1,                      \
    +          "Additional pacing tax surcharge to help unclutter the heap. "    \
    +          "Larger values makes the pacing more aggressive. Lower values "   \
    +          "risk GC cycles finish with less memory than were available at "  \
    +          "the beginning of it.")                                           \
    +          range(1.0, 100.0)                                                 \
    +                                                                            \
    +  experimental(uintx, ShenandoahCriticalFreeThreshold, 1,                   \
    +          "Percent of heap that needs to be free after recovery cycles, "   \
    +          "either Degenerated or Full GC. If this much space is not "       \
    +          "available, next recovery step would triggered.")                 \
    +          range(0, 100)                                                     \
    +                                                                            \
    +  diagnostic(bool, ShenandoahDegeneratedGC, true,                           \
    +          "Use Degenerated GC as the graceful degradation step. Disabling " \
    +          "this leads to degradation to Full GC")                           \
    +                                                                            \
    +  experimental(uintx, ShenandoahFullGCThreshold, 3,                         \
    +          "How many back-to-back Degenerated GCs to do before triggering "  \
    +          "a Full GC.")                                                     \
    +                                                                            \
    +  experimental(bool, ShenandoahImplicitGCInvokesConcurrent, false,          \
    +          "Should internally-caused GCs invoke concurrent cycles, or go to" \
    +          "stop-the-world (degenerated/full)?")                             \
    +                                                                            \
    +  experimental(bool, ShenandoahHumongousMoves, true,                        \
    +          "Allow moving humongous regions. This makes GC more resistant "   \
    +          "to external fragmentation that may otherwise fail other "        \
    +          "humongous allocations, at the expense of higher GC copying "     \
    +          "costs.")                                                         \
    +                                                                            \
    +  diagnostic(bool, ShenandoahOOMDuringEvacALot, false,                      \
    +          "Simulate OOM during evacuation frequently.")                     \
    +                                                                            \
    +  diagnostic(bool, ShenandoahAllocFailureALot, false,                       \
    +          "Make lots of artificial allocation failures.")                   \
    +                                                                            \
    +  diagnostic(bool, ShenandoahTerminationTrace, false,                       \
    +          "Tracing task termination timings")                               \
    +                                                                            \
    +  develop(bool, ShenandoahVerifyObjectEquals, false,                        \
    +          "Verify that == and != are not used on oops. Only in fastdebug")  \
    +                                                                            \
    +  diagnostic(bool, ShenandoahAlwaysPreTouch, false,                         \
    +          "Pre-touch heap memory, overrides global AlwaysPreTouch")         \
    +                                                                            \
    +  experimental(intx, ShenandoahMarkScanPrefetch, 32,                        \
    +          "How many objects to prefetch ahead when traversing mark bitmaps."\
    +          "Set to 0 to disable prefetching.")                               \
    +          range(0, 256)                                                     \
    +                                                                            \
    +  experimental(uintx, ShenandoahMarkLoopStride, 1000,                       \
    +          "How many items are processed during one marking step")           \
    +                                                                            \
    +  experimental(uintx, ShenandoahParallelRegionStride, 1024,                 \
    +          "How many regions are processed in one stride during parallel "   \
    +          "iteration.")                                                     \
    +                                                                            \
    +  experimental(size_t, ShenandoahSATBBufferSize, 1 * K,                     \
    +          "Number of entries in an SATB log buffer.")                       \
    +          range(1, max_uintx)                                               \
    +                                                                            \
    +  experimental(uintx, ShenandoahSATBBufferFlushInterval, 100,               \
    +          "Forcefully flush non-empty SATB buffers at this interval. "      \
    +          "Time is in milliseconds.")                                       \
    +                                                                            \
    +  experimental(uint, ShenandoahParallelSafepointThreads, 4,                 \
    +          "Number of parallel threads used for safepoint prolog/epilog")    \
    +                                                                            \
    +  experimental(bool, ShenandoahPreclean, true,                              \
    +          "Do concurrent preclean phase before final mark: process "        \
    +          "definitely alive references to avoid dealing with them during "  \
    +          "pause.")                                                         \
    +                                                                            \
    +  experimental(bool, ShenandoahSuspendibleWorkers, false,                   \
    +          "Suspend concurrent GC worker threads at safepoints")             \
    +                                                                            \
    +  diagnostic(bool, ShenandoahSATBBarrier, true,                             \
    +          "Turn on/off SATB barriers in Shenandoah")                        \
    +                                                                            \
    +  diagnostic(bool, ShenandoahKeepAliveBarrier, true,                        \
    +          "Turn on/off keep alive barriers in Shenandoah")                  \
    +                                                                            \
    +  diagnostic(bool, ShenandoahWriteBarrier, true,                            \
    +          "Turn on/off write barriers in Shenandoah")                       \
    +                                                                            \
    +  diagnostic(bool, ShenandoahReadBarrier, true,                             \
    +          "Turn on/off read barriers in Shenandoah")                        \
    +                                                                            \
    +  diagnostic(bool, ShenandoahStoreValEnqueueBarrier, false,                 \
    +          "Turn on/off enqueuing of oops for storeval barriers")            \
    +                                                                            \
    +  diagnostic(bool, ShenandoahStoreValReadBarrier, true,                     \
    +          "Turn on/off store val read barriers in Shenandoah")              \
    +                                                                            \
    +  diagnostic(bool, ShenandoahCASBarrier, true,                              \
    +          "Turn on/off CAS barriers in Shenandoah")                         \
    +                                                                            \
    +  diagnostic(bool, ShenandoahAcmpBarrier, true,                             \
    +          "Turn on/off acmp barriers in Shenandoah")                        \
    +                                                                            \
    +  diagnostic(bool, ShenandoahCloneBarrier, true,                            \
    +          "Turn on/off clone barriers in Shenandoah")                       \
    +                                                                            \
    +  diagnostic(bool, ShenandoahStoreCheck, false,                             \
    +          "Emit additional code that checks objects are written to only"    \
    +          " in to-space")                                                   \
    +                                                                            \
    +  experimental(bool, ShenandoahConcurrentScanCodeRoots, true,               \
    +          "Scan code roots concurrently, instead of during a pause")        \
    +                                                                            \
    +  experimental(uintx, ShenandoahCodeRootsStyle, 2,                          \
    +          "Use this style to scan code cache:"                              \
    +          " 0 - sequential iterator;"                                       \
    +          " 1 - parallel iterator;"                                         \
    +          " 2 - parallel iterator with cset filters;")                      \
    +                                                                            \
    +  experimental(bool, ShenandoahOptimizeStaticFinals, true,                  \
    +          "Optimize barriers on static final fields. "                      \
    +          "Turn it off for maximum compatibility with reflection or JNI "   \
    +          "code that manipulates final fields.")                            \
    +                                                                            \
    +  experimental(bool, ShenandoahOptimizeInstanceFinals, false,               \
    +          "Optimize barriers on final instance fields."                     \
    +          "Turn it off for maximum compatibility with reflection or JNI "   \
    +          "code that manipulates final fields.")                            \
    +                                                                            \
    +  experimental(bool, ShenandoahOptimizeStableFinals, false,                 \
    +          "Optimize barriers on stable fields."                             \
    +          "Turn it off for maximum compatibility with reflection or JNI "   \
    +          "code that manipulates final fields.")                            \
    +                                                                            \
    +  diagnostic(bool, ShenandoahDecreaseRegisterPressure, false,               \
    +          "Try to reuse after-barrier values to reduce register pressure")  \
    +                                                                            \
    +  experimental(bool, ShenandoahCommonGCStateLoads, false,                   \
    +         "Enable commonming for GC state loads in generated code.")         \
    +                                                                            \
    +  develop(bool, ShenandoahVerifyOptoBarriers, false,                        \
    +          "Verify no missing barriers in C2")                               \
    +                                                                            \
    +  experimental(bool, ShenandoahDontIncreaseWBFreq, true,                    \
    +          "Common 2 WriteBarriers or WriteBarrier and a ReadBarrier only "  \
    +          "if the resulting WriteBarrier isn't executed more frequently")   \
    +                                                                            \
    +  experimental(bool, ShenandoahLoopOptsAfterExpansion, true,                \
    +          "Attempt more loop opts after write barrier expansion")           \
    +

See also proposed webrev for review:
http://cr.openjdk.java.net/~rkennke/shenandoah-upstream/00/shenandoah-complete/


Comments
Moving to Approved. Note that per the command line evolution policy, (https://wiki.openjdk.java.net/display/HotSpot/Hotspot+Command-line+Flags%3A+Kinds%2C+Lifecycle+and+the+CSR+Process), if at some point the Shenandoah flags want to go to "product" or "manageable" flags, a CSR would be needed for that change.
06-12-2018

It has been pointed out that turning off GC barriers using one of the -XX:-ShenandoahXYZBarrier flags may lead to spec-violating behaviour. Turning off barriers like this is only safe in 'passive' mode, where Shenandoah does not require any barriers. We added additional checks in shenandoahArguments.cpp that reject spec-violating combinations of such flags. See: http://mail.openjdk.java.net/pipermail/shenandoah-dev/2018-November/008536.html
04-12-2018

Repeating a comment from another issue, I think this request would benefit from CSR review even as an experimental feature.
30-11-2018

Kim just pointed out elsewhere, that CSR is not really required for experimental and diagnostic flags. We only have experimental and diagnostic flags here. Does this mean that I could/should withdraw this CSR? I don't mind getting feedback on the proposed changes though. I just don't want it to block anything or unnecessarily draw resources from e.g. reviewing Shenandoah or anything else ;-) http://mail.openjdk.java.net/pipermail/hotspot-gc-dev/2018-November/024084.html
29-11-2018

> Was a shorter option prefer than "Shenandoah" considered? Yes. We (shenandoah devs) do use shorthands like ShHeapRegionSize or even ShHRSize when communicating internally, but we know what it means. It seems rather obscure though. Shenandoah prefix seems clearer. > For naming something like "ShenandoahSATBBarrier" please consider > using "ShenandoahSatbBarrier" instead. The JDK API is not consistent > on this point, but camel-casing acronyms in API declarations is now > preferred. I would not like to change acronyms in flags like SATB to Satb. This would look *very* odd to me, and inconsistent too. Every other flag that has SATB in it uses just SATB. Other such acronyms used in our flags are: GC, TLAB and CAS. I don't think any of them are better as Gc, Tlab or Cas. I'd very much prefer to keep them as they are. > Do ShenandoahOptimizeInstanceFinals and related options enable > optimizations which violate the spec? It taps undefined behavior: when modifying a final field via reflection or JNI or other means, the optimization might lead to see stale values. Another related case is when a final field is initialized in a constructor, and the object escapes and the field is accessed before the initializer completes. This seems to be another UB. https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3 Therefore, these options do not violate the spec, *but* they can break applications that assume that finals are stronger than they are. This is similar to TrustFinalNonStaticFields, for example, which can break applications the same way, while being formally correct. Premature publication already breaks final field guarantees in subtle manner. > Are there general memory management options which Shenandoah pays > attention to or ignores? We use ParallelGCThreads, ConcGCThreads, ClassUnloading, ClassUnloadingWithConcurrentMark and probably some more. Do you want me to dig them up and document somewhere? (Where?) > Before the request is finalized for the second phase of CSR review, please have at least one GC engineer review the CSR. Ok, I pinged hotspot-gc-dev: http://mail.openjdk.java.net/pipermail/hotspot-gc-dev/2018-November/024042.html Thanks, Roman
29-11-2018

A few comments/questions: Was a shorter option prefer than "Shenandoah" considered? For naming something like "ShenandoahSATBBarrier" please consider using "ShenandoahSatbBarrier" instead. The JDK API is not consistent on this point, but camel-casing acronyms in API declarations is now preferred. Do ShenandoahOptimizeInstanceFinals and related options enable optimizations which violate the spec? Are there general memory management options which Shenandoah pays attention to or ignores? Before the request is finalized for the second phase of CSR review, please have at least one GC engineer review the CSR. Moving to Provisional.
29-11-2018