官方:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。
JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,
所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。
PermGen space:全称是Permanent Generation space,即永久代。就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域,GC(Garbage Collection)应该不会对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
Heap space:存放Instance。
Java Heap分为3个区,Young即新生代,Old即老生代和Permanent。
Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象。
设置项 | 说明 |
---|---|
-Xms512m | 表示JVM初始分配的堆内存大小为512m(JVM Heap(堆内存)最小尺寸,初始分配) |
-Xmx1024m | JVM最大允许分配的堆内存大小为1024m,按需分配(JVM Heap(堆内存)最大允许的尺寸,按需分配) |
-XX:PermSize=512M | JVM初始分配的非堆内存 |
-XX:MaxPermSize=1024M | JVM最大允许分配的非堆内存,按需分配 |
-XX:NewSize | 定义YOUNG段的尺寸,NewSize为JVM启动时YOUNG的内存大小 |
-XX:MaxNewSize | MaxNewSize为最大可占用的YOUNG内存大小 |
-XX:SurvivorRatio | 设置YOUNG代中Survivor空间和Eden空间的比例 |
1 | -Xmx2000M -Xms2000M -Xmn500M |
Serial Collector
大部分平台或者强制 java -client 默认会使用这种。
young generation算法 = serial
old generation算法 = serial (mark-sweep-compact)
这种方法的缺点很明显, stop-the-world, 速度慢。服务器应用不推荐使用。
Parallel Collector
在linux x64上默认是这种,其他平台要加 java -server 参数才会默认选用这种。
young = parallel,多个thread同时copy
old = mark-sweep-compact = 1
优点:新生代回收更快。因为系统大部分时间做的gc都是新生代的,这样提高了throughput(cpu用于非gc时间)
缺点:当运行在8G/16G server上old generation live object太多时候pause time过长
Parallel Compact Collector (ParallelOld)
young = parallel = 2
old = parallel,分成多个独立的单元,如果单元中live object少则回收,多则跳过
优点:old old generation上性能较 parallel 方式有提高
缺点:大部分server系统old generation内存占用会达到60%-80%, 没有那么多理想的单元live object很少方便迅速回收,同时compact方面开销比起parallel并没明显减少。
Concurrent Mark-Sweep(CMS) Collector
young generation = parallel collector = 2
old = cms
同时不做 compact 操作。
优点:pause time会降低, pause敏感但CPU有空闲的场景需要建议使用策略4.
缺点:cpu占用过多,cpu密集型服务器不适合。另外碎片太多,每个object的存储都要通过链表连续跳n个地方,空间浪费问题也会增大。
jmap -heap 查看java 堆(heap)使用情况
1 | jmap -heap pid |
jmap [ option ] pid (to connect to remote debug server)
jmap [ option ] executable core (to connect to remote debug server)
jmap [ option ] [server-id@]remote-hostname-or-IP (to connect to remote debug server)
[option] is one of:
jmap -dump:live,format=b,file=heap.bin
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
- jmap -histo:live pid>a.log
可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。 可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。
jmap -histo:live 这个命令执行,JVM会先触发gc,然后再统计信息。
- jmap -dump:live,format=b,file=a.log pid
JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用。
1 | echo 1 >/proc/sys/vm/drop_caches |