I try to use G1GC with my program. Program is used on various machines with various memory size: VPS with 1Gb memory (minimum), desktop with 8Gb memory, DS with 32Gb memory (maximum). I noticed that G1GC not reserve more memory even if there is a lot of free memory (for example, G1GC not reserve more than 3Gb on my machine with 8Gb total / 4Gb free)
P.S. I want to have universal solution. I cannot create separate version or separate run script for each type of machine.
I think you have chosen the wrong garbage collection algorithm. The Java 8 documentation offers this guidance:
Selecting a Collector
Unless your application has rather strict pause time requirements, first run your application and allow the VM to select a collector. If necessary, adjust the heap size to improve performance. If the performance still does not meet your goals, then use the following guidelines as a starting point for selecting a collector.
If the application has a small data set (up to approximately 100 MB), then select the serial collector with the option
-XX:+UseSerialGC
.If the application will be run on a single processor and there are no pause time requirements, then let the VM select the collector, or select the serial collector with the option
-XX:+UseSerialGC
.If (a) peak application performance is the first priority and (b) there are no pause time requirements or pauses of 1 second or longer are acceptable, then let the VM select the collector, or select the parallel collector with
-XX:+UseParallelGC
.If response time is more important than overall throughput and garbage collection pauses must be kept shorter than approximately 1 second, then select the concurrent collector with
-XX:+UseConcMarkSweepGC
or-XX:+UseG1GC
.
Source: Selecting a Collector
Based on your comments, it seems that your goal is to get peak performance; i.e. minimize the overall time spent on GC and related overheads.
That means that your best options are:
If you want a one-size-fits all script that works irrespective of your hardware, the performance goal approach is best, though that means you won't be able to use platform-specific settings to (potentially) improve on the JVM's decisions.