继续上次【http://www.javashuo.com/article/p-ctjyidxk-cy.html】的理论继续。。有点吐血的感受,都不知道学了这么一大堆理论有何实际意义,自己JVM就是个理论体系比较多的东东,因此理论不得不去面对,继续硬着头皮往前进。html
内存结构程序员

这个在以前的学习中都已经学习过了,复习一下。web
内存分配算法
- 堆上分配
大多数状况在eden【年轻代中的一个区域】上分配,偶尔会直接在old【老年代】上分配,细节取决于GC的实现。
- 栈上分配
原子类型的局部变量。
内存回收安全
一、GC要作的是将那些dead的对象所占用的内存回收掉。数据结构
- Hotspot认为没有引用的对象是dead的。
- Hotspot将引用分为四种:Strong【强引用】、Soft【软引用】、Weak【弱引用】、Phantom【虚引用】,这是大伙熟知的。
一、Strong既默认经过Object o = new Object()这种方式赋值的引用。
二、Soft、Weak、Phantom这三种则是继续Reference。
二、在Full GC时会对Reference类型的引用进行特殊处理。多线程
- Soft:内存不够时必定会被GC、长期不用也会被GC。
- Weak:必定会被GC,当被mark为dead,会在ReferenceQueue中通知。
- Phantom:原本就没引用,当从jvm heap中释放时会通知。
以上的概念会在将来举例进行代码说明的,先有个印象。并发
垃圾收集算法dom

以上是一些比较经典的垃圾收集算法,下面会逐个进行说明。jvm
GC的时机
一、在分代模型的基础上,GC从时机上分为两种:Scavenge GC和Full GC。
二、Scavenge GC(Minor GC)
- 触发时机:新对象生成时,Eden空间满了。
- 理论上Eden区大多数对象会在Scavenge GC回收,复制算法的执行效率会很高,Scavenge GC时间比较短。
三、Full GC【这个在实际中必定得要避免】
- 对整个JVM进行整理,包括Young、Old和Perm。
- 主要的触发时机:1)Old满了;2)Perm满了;3)system.gc()
- 效率很低,尽可能减小Full GC。
垃圾回收器(Garbage Collector)
- 分代模型:GC的宏观愿景。
- 垃圾回收器:GC的具体实现。
- Hotspot JVM提供多种垃圾回收器,咱们须要根据具体应用的须要采用不一样的回收器。
- 没有万能的垃圾回收器,每种垃圾回收器都有本身的适用场景。
垃圾收集器的“并行”和“并发”
- 并行(Parallel):指多个收集器的线程同时工做,可是用户线程处于等待状态。
- 并发(Concurrent):指收集器在工做时同时,能够容许用户线程工做。
并发不表明解决了GC停顿的问题,在关键的步骤仍是要停顿。好比在收集器标记垃圾的时候。但在清除垃圾的时候,用户线程能够和GC线程并发执行。
Serial收集器
ParNew收集器
- ParNew收集器就是Serial的多线程版本,除了使用多个收集线程外,其他行为包括算法、STW、对象分配规则、回收策略等都与Serial收集器如出一辙。
- 对应的这种收集器是虚拟机运行在Server模式的默认新生代收集器,在单CPU的环境中,ParNew收集器并不会比Serial收集器有更好的效果。
- Serial收集器在新生代的多线程版本。
- 使用复制算法(由于针对新生代)。
- 只有在多CPU的环境下,效率才会比Serial收集器高。
- 能够经过-XX:ParallelGCThreads来控制GC线程数的多少。须要结合具体CPU的个数。
- Server模式下新生代的缺省收集器。
Parallel Scavenge收集器
- Parallel Scavenge收集器也是一个多线程收集器,也是使用复制算法,但它的对象分配规则与回收策略都与ParNew收集器有所不一样,它是以吞吐量最大化(既GC时间占总运行时间最小)为目标的收集器实现,它容许较长时间的STW换取总吞吐量最大化。
Serial Old收集器
- Serial Old是单线程收集器,使用标记-整理算法,是老年代的收集器。
Parallel Old收集器
- 老年代版本吞吐量优先收集器,使用多线程和标记一整理算法,JVM1.6提供,在此以前,新生代使用了PS收集器的话,老年代除Serial Old外别无选择,由于PS没法与CMS收集器配合工做。【了解既可】
- Parallel Scavenge在老年代的实现
- 在JVM1.6才出现Parallel Old
- 采用多线程,Mark-Compact算法
- 更注重吞吐量
- Parallel Scavenge + Parallel Old = 高吞吐量,但GC停顿可能不理想

CMS(Concurrent Mark Sweep)收集器【特别复杂的一种收集器】
- CMS是一种以最短停顿时间为目标的收集器,使用CMS并不能达到GC效率最高(整体GC时间最小),但它能尽量下降GC时服务的停顿时间,CMS收集器使用的是标记-清除算法。
- 追求最短停顿时间,很是适合Web应用。
- 只针对老年区,通常结合ParNew使用。
- Concurrent,GC线程和用户线程并发工做(尽可能并发)。
- Mark-Sweep。
- 只有在多CPU环境下才有意义 。
- 使用-XX:+UseConcMarkSweepGC打开。
- CMS以牺牲CPU资源的代价来减小用户线程的停顿。当CPU个数少于4的时候,有可能对吞吐量影响很是大。
- CMS在并发清理的过程当中,用户线程还在跑。这时候须要预留一部分空间给用户线程。
- CMS用Mark-Sweep,会带来碎片问题。碎片过多的时候会容易频繁触发Full GC。
GC垃圾收集器的JVM参数定义

Java内存泄漏的经典缘由
一、对象定义在错误的范围(Wrong Scope)。
二、异常(Exception)处理不当。
- 错误的作法

对于有经验的程序员应该不会出现上面的问题,可是这里只是抛出泄漏的场景。
- 正确的作法

三、集合数据管理不当。
- 当使用Array-based的数据结构(ArrayList,HashMap等)时,尽可能减小resize:
a、好比new ArrayList时,尽可能估算size,在建立的时候把size肯定。
b、减小resize能够避免没有必要的array copying,gc碎片等问题。
- 若是一个List只须要顺序访问,不须要随机访问(Random Access),用LinkedList代替ArrayList
a、LInkedList本质是链表,不须要resize,但只适用于顺序访问。
以上是对JVM垃圾回收相关理论的总体了解,说实话看完其实头晕晕的,不要紧,接下来则会用实践来反证理论。