须要反复记忆的东西--暂时无用

一  JVMhtml

     1.  栈帧包括:局部变量表、操做数栈、常量池、动态连接、方法出口信息等算法

     2.  方法区:堆的一个逻辑部分,线程共享,存放已经被虚拟机加载的类信息、常量、编程

                        静态变量、即时编译器编译后的代码等。数组

     3.  如何判断对象已死多线程

          对象不可达并经历两次标记的对象。并发

        (1)可达性分析算法函数

                 该算法的思路是经过一系列称为“GC Root”的对象做为始点,从这些节点开始向下搜索,性能

                 搜索所走过的路称为引用链(Reference Chain),当一个对象到GC Roots没有任何引this

                 用链相接(不可达)时,则证实此对象时不可用的。以下图所示,object五、object六、spa

                 object7虽然相会关联,可是它们到GC Root是不可达的,因此将会被断定为是可回收

                 的对象。

                 

                在Java中,可做为GC Root的对象包括下面几种:

                --  虚拟机栈(栈帧中的本地变量表)中引用的对象。

                --  本地方法栈中JNI(即通常说的Native方法)引用的对象

                --  方法区内类静态属性引用的对象和常量引用的对象。

          (2)可达性分析算法            

                   若是进行垃圾回收的时候发现一个对象没有在GC Root链上,那么就须要进行两次的

                   标记过程,若是当前发现没有关联在GC Root链上,那么就会进行第一次标记,若是

                   此时对象的finalize()方法没有被覆盖或该方法已经被虚拟机调用过,那么此时将被标

                   记为没有必要执行,此时该对象会被放入“即将回收”集合,不然就会放入F-Queue的

                   对象中等待执行finalize()方法,若是在此方法中对象将本身与GC Root链上的任何一

                   个对象关联(譬如把本身(this)赋值给某个类变量或者对象的成员变量),那么就

                   会被移出”即将回收“集合。

     4.  常见的垃圾回收算法

        (1)标记清除算法

                         分为两个阶段,标注和清除。标记阶段标记出全部须要回收的对象,清除阶段回

                         收被标记的对象所占用的空间,该算法最大的问题是内存碎片产生严重。

        (2)复制算法

                        为了解决Mark-Sweep算法内存碎片化的缺陷而被提出的算法。按内存容量将内存

                        划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复

                        制到另外一块上去,把已使用的内存清掉。这种算法虽然实现简单,内存效率高,不

                        易产生碎片,可是最大的问题是可用内存被压缩到了本来的一半。且存活对象增多

                        的话,Copying算法的效率会大大下降

        (3)标记压缩算法

                         标记阶段和标记算法相同,标记后不是清理对象而是将存活的对象移动到内存的

                         一端,而后清除边界外的对象。

        (4)分代算法

                        分代收集法是目前大部分JVM所采用的方法,其核心思想是根据对象存活的不一样

                        生命周期将内存划分为不一样的域,通常状况下将GC堆划分为老生代

                        (Tenured/Old Generation)和新生代(Young Generation)。老生代的特色是每次垃

                        圾回收时只有少许对象须要被回收,新生代的特色是每次垃圾回收时都有大量垃

                        圾须要被回收,所以能够根据不一样区域选择不一样的算法。新生代采用复制算法,

                        老年代采用标记压缩算法。

        (5)分区算法

                         将整个内存分为N个小的独立空间,每一个小空间均可以独立使用,这样细粒度控

                         制一次回收多少个小空间和哪些个小空间,而不是对整个空间进行GC,从而提

                         升性能。

     5.  垃圾回收器

         (1)Serial收集器

                           新生代收集器,是一个单线程的收集器,采用的是“复制算法”。它的 “单线程”

                           的意义并不只仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工

                           做,更重要的是在它进行垃圾收集时,必须暂停其它全部工做线程,直到它收

                           集结束。

         (2)ParNew收集器

                           是Serial收集器的多线程版本,采用的是“复制算法”。除了使用多线程进行垃圾

                           收集以外,其他行为包括Serial收集器可用的全部控制参 数、收集算法、

                           Stop The World、对象分配规则、回收策略等都与Serial收集器彻底同样,在

                           实现上,这两种收集器也共用了至关多的代码。ParNew收集器除了多线程收集

                           以外,其它与Serial收集器相比并无太多创新之处,但它倒是运行在Server模

                           式下的虚拟机中首选的新生代收集器,其中一个与性能无关但很重要的缘由是,

                           除了Serial收集器外,目前只有它能与CMS收集器配合工做。

         (3)Parallel Scavenge收集器:

                          是工做在新生代的垃圾回收器,使用了复制算法,也是多线程独占(独占回收器:

                          GC来的时候应用停顿只执行GC)形式的收集器,它的特色是关注系统的吞吐量。

         (4)Serial Old收集器:

                          是Serial收集器的老年代版本,它一样是一个单线程的收集器,使用“标记-整理”

                          算法。这个收集器的主要意义也是在于给Client模式下的虚拟机使用。若是在

                          Server模式下,那么它主要还有两大用途:

                          一种用途在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用。

                          另外一种用途就是做为CMS收集器的后备方案,在并发收集器发生

                          Concurrent Mode Failure时使用。

         (5)Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。

                   这个收集器在JDK1.6中才开始提供的,在此以前,新生代的Parallel Scavenge收集器

                   一直处于比较尴尬大的状态。缘由是若是新生代选择了Parallel Scavenge收集器,老

                   年代除了Serial Old收集器外别无选择。因为老年代Serial Old收集器在服务端性能上

                   的拖累,使用Parallel Scavenge收集器也未必能在总体应用上得到吞吐量最大的效果。

                   直到。

        (6)CMS回收器:

                 工做在老年代的回收器,使用的是标记清除法,是一种以获取最短回收停顿时间为目标

                 的收集器主要关注的是系统的停顿时间。CMS并非独占的回收器,也就是说CMS回

                 收的过程当中,应用程序仍然在不停的工做,又会有新的垃圾不断产生,因此在使用CMS

                 过程当中应该确保应用程序的内存足够可用,CMS不会等到应用程序饱和的时候在去回收

                 圾,而是到达某个阈值的时候就去回收,回收的阈值能够经过指定的参数来设置

                 -XX:CMSInitiatingOccupancyFraction来指定,默认值是68,也就是说当老年代的使用率

                 达到68%的时候会执行CMS垃圾回收,若是内存使用增加的很快,在CMS过程当中出现了

                 内存不足的状况,CMS回收就会失败,虚拟机将启用老年代串行回收器进行垃圾回收,

                 这会致使应用程序中断,直到垃圾回收完成后才会正常工做,这个过程GC停顿时间可能

                 过长,因此设置-XX:CMSInitiatingOccupancyFraction要根据实际状况。

                 运做过程:初始标记、并发标记、从新标记、并发清除。有的版本叫(另外CMS收集

                 器比较详细的步骤查看:https://blog.csdn.net/zqz_zqz/article/details/70568819

                 初始标记、从新标记这两个步骤仍需“Stop The World”。初始标记仅仅只是标记一下

                 GC Root能直接关联到的对象不包括间接到达的哈,没有直接关联的对象在并发标记

                 阶段标记哈),速度很快;并发标记阶段就是进行GC Roots Tracing的过程从新标记

                 则是为了修正并发标记期间因用户程序继续而致使标记产生变更的那一部分对象的标记

                 记录,这个时间的停顿时间通常会比初始标记阶段稍长些,但远比并发标记短。在这个

                 阶段暂停全部用户线程,从新扫描堆中的对象,进行可达性分析,标记活着的对象,特

                 别须要注意一点,这个阶段是以新生代中对象为根来判断对象是否存活的;并发清除,

                 这个阶段主要是清除那些没有标记的对象而且回收空间,因为CMS并发清理阶段用户线

                 程还在运行着,伴随程序运行天然就还会有新的垃圾不断产生,这一部分垃圾出如今标

                 记过程以后,CMS没法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这

                 一部分垃圾就称为“浮动垃圾”。

                 缺点:

                 (A)CMS收集器对CPU资源很是敏感(其实应该说它比较消耗cpu资源)。在并

                           发阶段,它虽然不会致使用户线程停顿,可是会由于占用一部分CPU资源而

                           致使应用程序变慢。CMS默认启动的回收器线程数量是 (CPU数量+3) / 4,

                           也就是当CPU在4个以上时,并发回收时垃圾收集线程很多于25%的CPU

                           资源,而且随着CPU数量的增长而降低。可是当CPU的数量不足时(譬

                           如2个),CMS对用户程序的影响就可能变得很大。为了应付这种状况,

                           虚拟机提供了一种称为“增量式并发收集器”(i-CMS)的CMS收集器变种,

                           就时在并发标记、清理的时候让GC线程、用户线程交替运行,尽可能减小线

                           程的独占资源的时间。在目前版本中i-CMS已经被声明为“deprecated”,即

                           不在提倡用户使用。

                 (B)CMS处理器没法处理浮动垃圾。

                 (C)基于“标记-清除”算法实现的收集器,会产生大量额空间碎片,会出现并发

                           模式失败的状况,并发模式失败就要执行内存整理(内存压缩),这种情

                           况下会致使CMS比Parallel Scavenge更慢(一般状况下CMS比

                           Parallel Scavenge要快)。

        (7)G1回收器:

                 是JDK1.7中提出的基于“标记-整理”算法的垃圾回收器,它的使命是取代CMS

                 回收器,可创建可预测的停顿时间模型属于分代垃圾回收器 区分新生代和老

                 年代,依然有eden和from、to区,它不要求新生代、老年代、eden、from、

                 to区空 间都 连续,使用了分区算法。听说JDK1.7以后使用的是G1回收算法,

                 不过有待考证,目前不能肯定,可是在

                 JDK1.7里它还不太成熟。

                        G1收集器将整个Java堆划分为大小相等的独立区域(Region),虽然还

                 保留着新生代和老年代的概念,但新生代和老年代再也不是物理隔离的了,它

                 们都是一部分Region(不须要连续)的集合。

                        G1收集器之因此能创建可预测的停顿时间模型,是由于它能够有计划

                 地避免在整个Java堆中进行全区域的垃圾收集。G1跟踪各个堆里面的垃圾

                 堆积的价值大小(回收所得到的空间大小以及回收所须要时间的经验值),

                 在后台维护一个优先列表,每次根据容许的回收时间,优先回收价值最大

                 的Region。

                 特色:

                 并行和并发:G1充分利用多CPU、多核环境下的硬件优点,使用多个CPU

                                      来缩短Stop-The-World停顿的时间,部分其它收集器本来须要

                                       停顿Java线程执行的GC动做,G1收集器仍然能够经过并发的

                                        方式让Java程序继续执行。

                 分代收集:存在Eden、from、to。不须要其它收集器的配合就能独立管理

                                   整个GC堆,能够本身处理堆中的对象。

                 空间整合:重总体来看是基于“标记-整理”算法实现的;局部(两个Region

                                   之间)来看是基于“复制”算法的实现的,但这两种算法都不会

                                   产生内存碎片。

                 可预测停顿:能创建可预测的停顿时间模型。能让使用者明确指定一个长

                                      度为M毫秒的时间片断内,消耗在垃圾收集上的时间不得超

                                      过N毫秒。(这点是G1相对于CMS的另一大优点,低停

                                      顿是G1和CMS共同的关注点,但G1除了追求低停顿外,还

                                      能创建可预测的停顿时间模型)

                 执行过程:若是不计算维护Remembered Set的操做,G1收集器的运做

                                   大体可划分为如下几个步骤:

                                   初始标记、并发标记、并行标记、最终标记、筛选回收。

                                   初始标记仅仅是标记一下GC Root能直接关联到的对象,并

                                   且修改TAMS(Next Top at Mark Start)的值,让下一阶段

                                   用户程序并发运行时,能在正确可用的Region中建立对象,

                                   这阶段须要停顿但时耗时短;并发标记是从GC Root开始对

                                   堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,

                                   但可与用户程序并发执行;最终标记是为了修正在并发标记期

                                    间因用户程序继续运做而致使标记产生变更的那一部分标记记

                                    录;筛选回收阶段首先要对各个Region的回收价值和成本进行

                                   排序,根据用户所指望的GC停顿时间来制定回收计划,根据

                                   Sun公司透露的信息来看,这个阶段其实能够作到与用户程序

                                   一块儿并发执行。

  

     6.  减小GC开销的编程技巧

           http://www.importnew.com/10472.html

         (1)不要显式调用System.gc()

                  此函数建议JVM进行主GC,虽然只是建议而非必定,但不少状况下它

                  会触发主GC,从而增长主GC的频率,也即增长了间歇性停顿的次数。

         (2)尽可能减小临时对象的使用

                  临时对象在跳出函数调用后,会成为垃圾,少用临时变量就至关于

                  减小了垃圾的产生,从而延长了出现上述第二个触发条件出现的时

                  间,减小了主GC的机会。

         (3)尽可能使用StringBuffer,而不用String来累加字符串

             因为String是固定长的字符串对象,累加String对象时,并不是在一个

                  String对象中扩增,而是从新建立新的String对象,如

                  Str5=Str1+Str2+Str3+Str4,这条语句执行过

                  程中会产生多个垃圾对象,由于对次做“+”操做时都必须建立新的

                  String对象,但这

                  些过渡对象对系统来讲是没有实际意义的,只会增长更多的垃圾。

        (4)计划好List的容量

                 像ArrayList这样的动态集合用来存储一些长度可变化数据的基本结

                 构。ArrayList和一些其余的集合(如HashMap、TreeMap),底层

                 都是经过使用Object[]数组来实现的。而String(它们本身包装在

                 char[]数组中),char数组的大小是不变的。那么问题就出现了,

                 若是它们的大小是不变的,咱们怎么能放item记录到集合中去呢?

                 答案显而易见:分配更多的数组。因此,不管何时,尽量

                 的给List或者Map分配一个初始容量,就像这样。

        (5)能用基本类型如Int,long,就不用Integer,Long对象

                 基本类型变量占用的内存资源比相应对象占用的少得多,若是没有

                 必要,最好使用基本变量。

        (6)尽可能少用静态对象变量

                 静态变量属于全局变量,不会被GC回收,它们会一直占用内存。

        (7)对象不用时最好显式置为Null

                 通常而言,为Null的对象都会被做为垃圾处理,因此将不用的对象显

                 式地设为Null,有利于GC收集器断定垃圾,从而提升了GC的效

                 率。

        (8)分散对象建立或删除的时间(我的以为这个彷佛不太现实)

                 集中在短期内大量建立新对象,特别是大对象,会致使忽然须要大

                 量内存,JVM在面临这种状况时,只能进行主GC,以回收内存或

                 整合内存碎片,从而增长主GC的频率。集中删除对象,道理也是一

                 样的。它使得忽然出现了大量的垃圾对象,空闲空间必然减小,从

                 而大大增长了下一次建立新对象时强制主GC的机会。

相关文章
相关标签/搜索