java之内存管理,内存溢出,垃圾回收(GC)

啊啊啊,阿里面试问到了java内存是怎么管理的,我当时睡蒙蔽了,自我感觉崩了,算法题也崩了,这个题当时问我我想了想,java内存管理,这是啥?好懵逼,我想想要不说说GC?说了一大堆也不知道对不对,回来一查资料,和我说的GC吻合度达到80%,唉,吃了没大局观的亏啊!!!!

下面只是简单放在一起,详细的还请看java内存区域(内存结构)与内存溢出异常(OOM)

首先讲讲java的内存分为哪几个区域

  1. 程序计数区 :为线程编号
  2. 虚拟机栈:Java方法执行的内存模型,每个方法被执行时都会创建一个栈帧
  3. 本地方法栈:Native方法服务
  4. 堆区 :存放对象实例,几乎所有的对象实例以及其属性都在这里分配内存
  5. 方法区:存储已经被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等数据。包含运行时的常量池

内存溢出(OOM)

  1. 虚拟机栈和本地方法栈溢出

StackOverflowError: 线程请求的栈深度大于虚拟机所允许的最大深度(循环递归)
OutOfMemoryError: 虚拟机在扩展栈是无法申请到足够的内存空间,一般可以通过不停地创建线程引起此种情况

  1. Java堆溢出:

当创建大量对象并且对象生命周期都很长的情况下,会引发OutOfMemoryError

  1. 运行时常量区溢出

OutOfMemoryError:PermGen space,这里一个典型的例子就是Stringintern方法,当大量字符串使用intern时,会触发此内存溢出

  1. 方法区溢出

方法区存放Class等元数据信息,如果产生大量的类(使用cglib),那么就会引发此内存溢出,OutOfMemoryError:PermGen space,在使用Hibernate等框架时会容易引起此种情况

垃圾回收器(GC)

这里深度绝对不够,但是勉强够用面试的了,

GC的流程(基本上所有的垃圾回收器都走这个,但是实现的方法不同)

  1. 找出堆中活着的对象
  2. 释放死对象占用的资源
  3. 定期调整活对象的位置

三个GC算法

下面三个算法都是在根搜索算法的基础上发展起来的

  1. 标记清除算法:标记所有从根节点开始的可达对象,清除未被标记的对象
  2. 复制算法:原来的内存空间分为2份,每次只使用一块,当清理的时候把存活对象复制到另一块内存块中,清除原来的那一块内存
  3. 标记整理算法:标记从根节点出发,把所有标记的压缩到内存的一边剩下空间的对象清除

复制算法适合于新生代 ,标记整理算法适合老年代

所以产生了分代收集算法:根据对象的存活周期的不同将内存分为几块,短命新生代,用复制算法,长命老年代用标记整理算法。

新生代到老年代的执行流程

上面既然说了新生代和老年代,那对象是怎么从新生代到老年代的呢?

新生代分为三个区域:一个 Eden和俩个Survivor,比例为8:1:1
后面1:1是为什么等新生代执行流程时你就懂了,那为什么8:1,
新对象除了特别大的,剩下的是先进Eden,所如果Eden不大,怎么能放开新对象呢?
在Eden中的对象满了之后就要移动到Survivor,这时是第一次新生代GC,可以猜一猜,Eden中的对象移动到Survivor的内存块是空的呢还是那个有对象的呢?答案是空的,没鸡腿,嘻嘻
这就是复制算法的好处,如果移动到有对象的Survivor就会造成内存的空间碎片化,是非常可怕的,尤其是Survivor不大的情况下,Eden中的对象和另一个Survivor中的对象一起移动到空的Survivor可以进行空间整理,这样可以压缩空间,减少内存空间的碎片化。

那新生代需要什么条件才能把对象移动到老年代?
答:在新生代进行15此MinorGC就会把年龄到15的放到老年代

老年代就用标记整理算法,当然也不是完全是标记整理算法,因为有的老年代垃圾回收器是用的标记清除算法

垃圾回收器

年轻代的垃圾回收器有三种:

  1. Serial :单线程的,
  2. ParNew :Serial 多线程模式
  3. ParallelScavenge :采用Copy算法,主要关注的是达到可控制的吞吐量,“吞吐量优先”,server默认新手回收器

老年代的垃圾回收器有四种

  1. Serial Old:Serial 老年代版本
  2. Parallel Old:Server模式的默认老年代收集器,关注点在吞吐量以及CPU资源敏感的场合使用
  3. CMS:使用标记清除,以获取最短回收停顿时间为目标的收集器,重视响应速度,希望系统停顿时间最短,对CPU资源非常敏感,越多越好
  4. G1:java7上线,主要使用标记-整理算法,不会产生碎片,将整个Java堆划分为多个大小相等的独立区域,对内存分段比较要求高,用于替代CMS

你可能感兴趣的:(java)