哪些内存须要回收?html
程序计数器,虚拟机栈,本地方法栈,这3个区域随线程而生,随线程而灭。这也是为何,逃逸分析技术,能帮助虚拟机减小GC次数(肯定域中的类,能够在栈上建立实例),优化代码,提升性能。java
须要回收的内存,主要是堆,方法区(线程共享的区域)。堆分为新生代(1/3),老年代(2/3),新生代下又分为Eden(8/10),s1(1/10),s2(1/10)。方法区,存放类信息,也被称为永久代。web
要作回收,首先要判断,对象是否存活。算法
目前是提供了这两种算法,不排除,之后不会有新的算法:tomcat
1.引用计数算法:引用计数放法,简单有效,可是很难解决对象之间相互循环引用的问题。安全
2.可达性分析算法:经过GC Roots 的对象做为起始点。当一个对象到GC Roots没有任何引用链相连,则证实此对象不可用。(经过OopMap,快速选择GC Roots,而oopmap 是在类加载完成的时候,虚拟机把对象内什么偏移量上是什么类型的数据计算出来。而oopMap的生成,只在安全点生成。安全点的选择,是以程序,是否具备让程序长时间执行的特征,我理解的,相对停留久的地方生成oop)多线程
当能判断对象,是否存活后。就将他们回收,JVM提供了3中回收对象的算法并发
1.标记,清除。将须要回收的对象,标记。而后清除。这样作,会产生空间碎片(逻辑上),而当须要申请内存时,没有连续的逻辑空间,可供申请。eclipse
2.复制。将内存分为两块儿,一样须要标记。内存快使用完时,将标记还存活的对象,复杂到另外一块内存区域。剩下内存,统一回收掉。jvm
3.标记,整理。一样时标记,可是将标记的须要回收内存,向一端移动。清理边界之外的内存
接下来
垃圾收集器,目前一共7中垃圾收集器。3种(Serial,ParNew,Parallel Scavenge),应用于新生代垃圾回收;3种(CMS,Serial old ,Paralel old)用于老年代的垃圾回收。最后一个G1收集器,既能针对于新生代,也能回收老年代。
了解垃圾收集器以前,应该先了解。并行和并发
并行:垃圾收集线程工做。应用线程等待。
并发:垃圾收集线程,应用线程,同时执行(并发执行。)
1.Serial 收集器:单线程收集器。主要时JDK1.3.1以前的收集器。如今已经不使用了。简单高效,适合运行在Client模式下
2.ParNew收集器::多线程收集器,能和CMS收集器搭配使用。(新生代,老年代收集器,并非全部都能搭配使用)。
3.Parallel Scavenge收集器:关注尽量缩短垃圾收集时,用户线程停顿时间,达到可控制的吞吐量。(和Parale old 搭配使用,时目前Jdk1.7,1.8的默认配置)
4.Serial old:一样是单线程收集器(标记,整理算法)
5.Parallel Old:多线程收集器(标记,整理算法)
6.CMS收集器:是一种获取最短回收停顿时间为目标的收集器。适合互联网,或者B/S系统服务端上。
7.G1收集器:每次根据容许的收集时间,优先回收价值最大的region。(jdk1.9默认配置)
CMS收集器和G1收集器,相对来讲复杂不少。大体分为:初始标记,并发标记,再次标记,回收。
说完完收集器。即是内存分配策略,和回收策略。
1.对象是优先在eden分配,没有足够空间时,执行Minor GC.(空间分配担保)
2.大对象直接在老年代分配。(大对象为何直接存放老年代呢?就由于老年代空间大?放老年代,不是会执行full gc嘛?)
3.长期存活的对象进入老年代。
4.动态对象年龄断定。(若是在survivor空间相同年龄多有对象大小的总和大于survivor空间的一半,则升到老年代)。
最后一个,就是如何查看,jvm版本信息。以及如何配置jvm内存;
配置jvm内存:
1.直接经过去执行class文件的时候,也能够设置JVM参数,eg : java -Xms512m -Xmx1024m HelloWorld
在cmd中设置,也必须是执行java命令时
堆栈是JVM分配的,通常涉及的时候都是启动JVM时。
2.eclipse能够在eclipse.ini 配置文件中设置,也能够在eclipse执行一个java类时,经过右键的参数添加部分去设置。
3.通常的像tomcat,weblogic这些web容器,都是应用jvm启动的,因此在他们的启动脚本中都会去调用JVM,就能够在他们的启动脚本中设置堆栈的大小。
查看JVM配置:
1.java -XX:+PrintFlagsFinal -version | grep :
2.java -XX:+PrintCommandLineFlags -version