堆(新生区,永久区,堆内存调优(jvm调优))
类的诞生,成长。甚至死亡(在幸存区也可能被Gc垃圾回收了)
逻辑假设:伊甸园区只能存10个对象,此时已经满了10个对象(已经满了)这个时候就触发一次轻Gc。然后可能就有的对象还存在引用那么就活下来了,有的对象可能已经不存在引用了就被垃圾回收了。活下来的就移动到幸存者区。假如活下来一个,那么上面的伊甸园区那么就又有10个空间了。当幸存区都满了就会触发一个重gc(full gc),还活着就进入养老区。当新生区和养老区都满了就会OOM(堆溢出)了
2、老年区
3、永久区存储区(永久区)(这个区域常驻内存跟对象没有关系,用来存放一些jdk自身class对象。Interface(接口)元数据),存储的是java运行时的一些环境或类信息(有时候可以理解为存放在我们磁盘里的),!!!这个区域不存在垃圾回收,关闭jvm就释放这个区域内存)
当一个启动类加载了大量的jar包 ,tomcat部署了太多的应用,或者大量动态生成的反射类。不断的被加载,知道内存满了。也会出现OOM
演变历程:
*jdk1.6前:永久代,常量池在方法区中
*jdk1.7 :永久代,但是开始退化了(去永久代)常量池在堆中
*jdk1.8之后:无永久代,常量池在元空间中(因为方法区在元空间,常量池在方法区嘛)
!!!上图的这个元空间逻辑上是存在的,但是物理上是不存在的
默认情况下的虚拟机和jvm的内存大小(以及和电脑运行内存的比例)
虚拟机分配的总内存是电脑内存的1/4,初始化的jvm内存是电脑内存的1/64。或者是虚拟机的1/16.
手动设置虚拟机和jvm的内存大小(前面的-Xmn/-Xmx虚拟机和jvm。+P后面是显示)
依次PSYong(新生代(eden(伊甸园区) from(幸存者区0) to(幸存者区1(后面这两个是动态的,每次清理都会互换下位置))))
ParOld(养老区(老年代))
Mete (元空间)
其中新生代+老年代就等于我们的堆内存了,这样元空间去哪里(所以是逻辑是存在的(在堆中,但是其物理上不存在))
堆内存溢出(OOM)调优方法
第一步:尝试扩大内存看结果(是否解决了堆溢出了)
第二步:分析内存,看那些地方出现了问题(JProfiler)
测试:(我们这里将前面的OOM,给他再设置个更小的jvm内存。看下输出)
看到了轻gc(Gc)和重Gc(full Gc)以及在的位置(这里是走完轻gc再走重Gc,这样又可以走轻Gc了,最后重Gc也满了)