记一次JVM内存调整

背景

线上环境的java进程,内存占用持续增高,没有下降的迹象。到网上看了几篇文章,结合以前看的书,对JVM参数进行了调整。

运行环境:linux + jetty


过程如下

1. 使用'top'命令查看java进程的'pid'(同时也能看到cup和内存使用率)

2. jmap -heap pid

使用该命令查看JVM的内存分配情况,举个例子(不是真实环境):

[root@localhost ~]# jmap -heap 21265
Attaching to process ID 21265, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03

using thread-local object allocation.
Parallel GC with 4 thread(s)				--当前使用的GC收集器

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 2025848832 (1932.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation<span style="white-space:pre">					</span>-- 新生代
</span>Eden Space:
   capacity = 116391936 (111.0MB)
   used     = 105991496 (101.08136749267578MB)
   free     = 10400440 (9.918632507324219MB)
   91.06429503844664% used
From Space:
   capacity = 12582912 (12.0MB)
   used     = 12552608 (11.971099853515625MB)
   free     = 30304 (0.028900146484375MB)
   99.75916544596355% used
To Space:
   capacity = 3145728 (3.0MB)
   used     = 0 (0.0MB)
   free     = 3145728 (3.0MB)
   0.0% used
PS Old Generation<span style="white-space:pre">					</span>--老年代
   capacity = 84410368 (80.5MB)
   used     = 23076840 (22.007789611816406MB)
   free     = 61333528 (58.492210388183594MB)
   27.338869083001747% used
PS Perm Generation
   capacity = 35127296 (33.5MB)
   used     = 34650048 (33.04486083984375MB)
   free     = 477248 (0.45513916015625MB)
   98.64137564132463% used

15850 interned Strings occupying 1578368 bytes.

分析一下这个配置存在的问题:

①MaxNewSize过高。NewSize和MaxNewSize设置得不同,会导致JVM动态调整新生代内存,产生额外的开销。

②From Space和To Space设置太小。新生代的内存回收算法使用'复制算法',就是利用这两个空间。设置太小会导致内存较大的对象晋升到老年代,无法及时回收

3. 针对这两个问题调整的参数

1)-XX:NewSize和-XX:MaxNewSize
用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。
2)-XX:SurvivorRatio
用于设置Eden和其中一个Survivor的比值,这个值也比较重要。比如4,那么eden:from:to=4:1:1,假如新生代内存为1024,那么eden区占682M,from和to占170M。


另外,

①使用jmap生成dump文件

[root@localhost ~]# jmap -dump:file=dump0812 21265
Dumping heap to /root/dump0812 ...
Heap dump file created

②使用jmap查看java类在内存中的使用情况

[root@localhost ~]# jmap -histo 21265 > 21265.log
[root@localhost ~]# vim 21265.log


 num     #instances         #bytes  class name
----------------------------------------------
   1:           628       41166656  [Lorg.apache.activemq.command.DataStructure;
   2:        181495       17662128  [C
   3:         83874       13812408  [B
   4:         21310       11787984  [I
   5:         62129        9034024  <constMethodKlass>
   6:         62129        7964432  <methodKlass>
   7:          5690        6305352  <constantPoolKlass>
   8:         52726        4218080  java.lang.reflect.Method
   9:          5689        4112944  <instanceKlassKlass>
  10:          4972        3777824  <constantPoolCacheKlass>
  11:        100670        2416080  java.lang.String
  12:         43910        2234608  [Ljava.lang.Object;
  13:         36393        1164576  java.util.HashMap$Entry
  14:          1780         966400  <methodDataKlass>
  15:         13277         946248  [S
  16:         19086         763440  java.util.concurrent.ConcurrentHashMap$ValueIterator
  17:         30792         739008  java.util.IdentityHashMap$EntryIterator$Entry
  18:          6050         727096  java.lang.Class
  19:          7998         575856  java.lang.reflect.Field
  20:         26766         557504  [Ljava.lang.Class;
  21:         11266         540768  java.util.HashMap
  22:         21420         514080  java.lang.StringBuilder
  23:          4604         502304  [Ljava.util.HashMap$Entry;
  24:          8911         461960  [[I
  25:         13733         329592  java.util.ArrayList
  26:          7900         316000  java.lang.ref.SoftReference
  27:          1470         249152  [Ljava.lang.reflect.Method;
  28:          7595         243040  java.util.concurrent.locks.ReentrantLock$NonfairSync
  29:          7591         242912  java.lang.ref.WeakReference
  30:          3182         229104  java.lang.reflect.Constructor
  31:          5864         205512  [Ljava.lang.String;

③这里使用的是parallel收集器,此时设置JVM参数SurvivorRatio无效,网友的回答是这样的:

HotSpot VM里,ParallelScavenge系的GC(UseParallelGC / UseParallelOldGC)默认行为是SurvivorRatio如果不显式设置就没啥用。显式设置到跟默认值一样的值则会有效果。因为ParallelScavenge系的GC最初设计就是默认打开AdaptiveSizePolicy的,它会自动、自适应的调整各种参数

为了让这个参数有效,又修改了JVM使用的收集器为CMS:-XX:+UseConcMarkSweepGC


最终
-XX:NewSize=1024
-XX:MaxNewSize=1024
-XX:SurvivorRatio=4

-XX:+UseConcMarkSweepGC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值