Assuming you did not add the -histo: live option when you took jmap, which will cause the report to contain garbage + live objects, and, referring to a memory drop, happened when you manually clicked βRun GCβ, I I doubt that the application has a memory leak, and an indicator of the promotion of bad objects from Young Gen to Old Gen. . In the end, the old Gen will be full and will run the full GC, the resulting application does not respond.
If my assumption is correct, I think that your strategy should be to minimize the promotion of objects in the old gene. Instead of worrying about what to do to clean the Old Gene, which is more expensive. Referring to the comments below, I think the application has a small memory size (<0.5G) relative to the maximum allocated memory of 7G.
"All of my data-dependent variables are defined in the method. When the method returns, these variables must be fixed, right?"
So there are a few things you can do.
Configure the application to minimize the response time of your transactions so that objects are garbage collected before being added to the old general
Increase the size of Young Gen. Since you have about 7 GB for the game, why don't you allocate about 2 - 3 GB for Young Gen to run (ie -XX: NewSize = 2g). A large new size will reduce the frequency of PCSacavenge (Young Collections) and reduce the aging rate of living objects.
Then start setting -XX: MaxTenuringThreshold = n. You can use gc.log with -XX: + PrintTenuringDistribution. Survival Ratio Size -XX: SurvivorRatio = n. Note that the option -XX: + UseAdaptiveSizePolicy is enabled by default, which dynamically changes the original size of Survivor coefficients. Alternatively, you can skip determining the ratio of survivors, leaving AdaptiveSizePolicy to complete the task. But I'm not a big fan of AdaptiveSizePolicy.
Along with AdaptiveSizePolicy, you can use -XX: MaxGCPauseMillis = n to instruct the garbage collector about the suspensions that you expect in your application when cleaning up the old general. In this way, the Collector will try to reach MaxGCPauseMillis without waiting until there is too much work.
Or you can switch to the CMS collector, which is designed to handle such problems.
Well, I think if the first two steps solve your problem, then you can leave the others aside. You should not spoil a good application by adding some additional things. The important thing is that you must configure the GC step by step.
source share