我们学习的jvm都是sun公司出的基于hotspot的jvm。
jvm堆的结构
- 新生代:eden区,幸存0区,幸存1区
- 老年代
- 元空间(堆外内存,方法区)
因为大部分java中的对象都是朝生夕死,所以搞了这一套gc(garbage collection)体系。
new出来的对象先放到eden区
当eden区满了之后,进行一次minor gc,把eden区存活的对象移到幸存的to区,把幸存的from区的存活对象也移到to区(达到规定次数默认15次后移入老年区)。
当新生区全满了之后,触发一次major gc,等于全gc了一次
全放满了就OOM(outofmemory)
默认情况下,分配的总内存是电脑内存的1/4,初始化的内存1/64
Jprofile和加参数看信息---这些先占个坑
*是栈满了,OOM是堆中占满无法创造新对象了
以下代码可以测试OOM错误
public class OOMTest { public static void main(String[] args) { List<Object> lists = new ArrayList<Object>(); for(int i=0;i<100000000;i++){ lists.add(new byte[1024*1024]); } } }
在IDEA中配置命令参数 -XX:+PrintGCDetails,可以输出详细的GC信息
可以看到信息非常丰富, 每一次GC都写出来了
配置如上图,可以充分配置内存。
使用Jprofiler可以对对象什么的进行更加细致的分析,需要生成dump文件(内存快照)
-XX:+HeapDumpOnOutOfMemoryError
GC
引用计数法:懂的都懂
复制算法:看图,不会有碎片,但是浪费了一半的幸存区空间。适合于存活度低的情况。
标记清除算法和标记压缩算法
标记清除算法,两个阶段,标记和清除
第一阶段:标记。从根结点出发遍历对象,对访问过的对象打上标记,表示该对象可达。
第二阶段:清除。对那些没有标记的对象进行回收,这样使得不能利用的空间能够重新被利用。
一堆碎片
这两种算法综合一下,称为分代收集算法