When a VM option is given an integer value (e.g., -XX:ActiveProcessorCount=123), the set_numeric_flag function in arguments.cpp is called:
https://github.com/openjdk/jdk/blob/cde923dd471a22cd69ea2cd4994bb16eba780804/src/hotspot/share/runtime/arguments.cpp#L841
The current implementation always calls strtoull() to get an unsigned 64-bit number, and then try to cast/truncate the result to the target type, and perform sign conversion as needed.
This is cumbersome and buggy, because the target type (such as intx) may have different bit-widths in different builds. Also, manual casting of unsigned to sign values can run into corner cases.
====================================================
Proposed design: use C++ templates and SFINAE to automatically choose the correct function for parsing the input string. The VM should avoid doing cast and size conversion as much as possible.
Also use a similar technique to write a comprehensive set of test cases to validate the implementation.
====================================================
Here are existing bugs (as of the above version)
(1) linux-x86/x64: ActiveProcessorCount is an int, but the VM doesn't catch the underflow:
$ ./images/jdk/bin/java -XX:ActiveProcessorCount=-0x80000001
Error occurred during initialization of VM
Too large parallelism for remembered sets.
(2) linux-x86: CICompilerCount is an intx (signed 32-bit), but the VM doesn't catch the overflow:
$ ./images/jdk/bin/java -XX:CICompilerCount=1T
CICompilerCount (0) must be at least 2
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
(3) linux-x86: MetaspaceSize is a size_t (unsigned 32-bit), but the VM doesn't catch the overflow:
$ ./images/jdk/bin/java -XX:MetaspaceSize=1234567812345678 -XX:+PrintFlagsFinal --version | grep size_t.MetaspaceSize
size_t MetaspaceSize = 937885696 {product} {command line}