[学習] 012ガベージコレクションアルゴリズム分析

概要ガベージコレクション

 注目すべき特徴で、Java言語は、ほとんどの頭痛は、もはやメモリ管理を考慮する必要がありませんプログラムの作成にJavaプログラマが可能なメモリ管理の問題を解決し、C ++プログラマを有効にするには、ガベージコレクションのメカニズムの導入です。ガベージコレクションのメカニズムがあるため、Javaオブジェクトは、「スコープ」という概念ではなくなりました、そして唯一のオブジェクト参照が全くありません「スコープを。」ガベージコレクションは、効果的にメモリリーク、空きメモリの有効利用を防ぐことができます。

  PS:メモリリークは、メモリ空間を使い切った後に回収されていない、一般的なケースでは複雑なデータ構造を必要としないプログラムを超えたメモリオブジェクトのライフサイクルは、時間の長さを必要とするよう、Javaのメモリリークが我々時々、見える意味しますこれはと呼ばれる「自由なオブジェクト。」

簡単に言えばガベージコレクション処理

  マーキングのプロセスを通過するには、少なくとも二回の到達不能オブジェクトが、直接ではなく、すぐに回復されますが、:ここでは、非常に重要な誤解を指摘しなければなりません。 
        最初のオブジェクトは、オブジェクトがファイナライズ()メソッドをオーバーライドするかどうかをチェックし、マークされています。あなたは、このメソッドをオーバーライドする場合は、キューF-クエリに置かれ、または直接オブジェクトに追加されたコレクションを「回復します」。第2のマーカーの前に、キュー内のすべてのF-クエリオブジェクトは、1ファイナライズ()メソッドで1を実行されますが、キューファイナライズ内のすべてのオブジェクトは、()メソッドは、JVMが低い優先順位を作成するので、それがある、行うことができることを保証するものではありません。実行するには、このキューのスレッドでの方法は、彼らが実行する権利を奪われていた、以前にトラバースされていないかもしれません。だから何を実行しているファイナライズ()メソッドはありますか?ファイナライズの実行中()メソッドの場合、このオブジェクトが再接続されるように、チェーンGCルーツは数字がキューからこのF-クエリオブジェクトの第二工程であろう参照:洗浄され、最後のを回避することを目的としますこの回復でクリアされるのを避けるために、クリアするには、回復は「通常」の対象となっています。しかし、どうやらこの事は、一度のオブジェクトファイナライズ()のために一度実行、無制限起こらないことはできない、と我々が標識されている場合は、その後、彼らはもはや唯一の運命をクリアするのを待って、ファイナライズ()メソッドを実行します。 
        後に、GCは、再び、第2の小スケールマークにキューF-キュー・オブジェクトとなり、回復から除去GCルーツ参照チェーン接続されたオブジェクトは、コレクションを「回復します」。このコレクション内のすべてのコンテンツは、リサイクルされます。

GC手動回復

パッケージcom.hongmoshui.sum。

パブリック クラスJVMDemo05 
{ 
    公共 静的 ボイドメイン(文字列[]引数)
    { 
        JVMDemo05 jvmDemo05 = 新しいJVMDemo05()。
        jvmDemo05 = nullを
        System.gc(); 
    } 

    保護 ボイド)(ファイナライズをスローしたThrowable 
    { 
        するSystem.out.println( "GC在回收对象を..." )。
    } 
}

アクションを確定

Javaの元技術は、ガベージコレクタのうち、メモリからオブジェクトを削除し、必要なクリーンアップを行うにはファイナライズ()メソッドを使用しています。この方法は、このオブジェクトが参照されるときに、このオブジェクトでガベージコレクタが呼び出されないことによって決定されます。これは、Objectクラスで定義されているので、すべてのクラスは、それを継承しています。サブクラスは、システムリソースを整理したり、その他のクリーンアップ作業を実行するためにファイナライズ()メソッドをオーバーライドします。()メソッドを確定ガベージコレクタがこのオブジェクトを呼び出す前にオブジェクトを削除することです。

メモリリーク

メモリリークの定義:またして引用されているため、オブジェクトは、アプリケーションを使用されていないが、ガベージコレクタは、それらを削除することはできません。

この定義を理解するためには、メモリ内のオブジェクトの状態を調べる必要があります。以下この図は、それが何であるかを説明し、どのような無用であることは参照されないオブジェクトをオブジェクト。

上図は、オブジェクト及び参照オブジェクトで参照されていないことが分かります。参照されていないオブジェクトがガベージコレクトされ、参照されたオブジェクトにはありません。いかなるオブジェクト、次いで、それを参照しないので、参照されないオブジェクトはもちろん、オブジェクトがもはや使用されません。しかし、すべての役に立たないが参照されないオブジェクトをオブジェクト。どちらも引用。これは、メモリリークが発生する場合です。

メモリリークを防ぐ方法

ここでは、メモリリークを防ぐためにアドバイスを使用して、いくつかの簡単です。

  • 特別な注意のHashMap、ArrayListのようなオブジェクトのコレクション、そして、彼らは多くの場合、メモリリークにつながります。これらはstaticとして宣言されている場合は、そのライフサイクルと限りアプリケーションのようになります。
  • イベントリスナーとコールバック関数には、特に注意してください。リスナーは、使用時には登録されているが、ときにもはや使用ではなく、抗登録。
  • クラスは独自のメモリ管理を持っている場合、開発者はメモリリークの問題よう注意する必要があります。」通常、いくつかのメンバ変数は、空の初期化に必要な時間を他のオブジェクトを参照します。

ガベージコレクションのアルゴリズム

参照カウント

1.1概要

その場所への参照は、カウンタ値が1だけインクリメントされるたびにカウンタ内のオブジェクトへの参照を追加するステップと、カウンタ0は、オブジェクトが使用中でなくなったではない任意の時間、ごみ、故障を参照する場合、カウンタ値が1だけ減少させますコレクタはオブジェクトが使用するメモリを再利用します。

1.2の長所と短所

利点:

参照カウントコレクターはすぐにプログラムの実行にインタリーブ、行わことができます。より有利な手順は、長い時間リアルタイム環境のために中断する必要はありません。

短所:

循環参照を検出することができません。親として、サブオブジェクト参照があり、順番に、親オブジェクトの子オブジェクト参照。このように、彼らは0に参照カウントとメモリの非常に無駄それぞれ加算と減算になることはありません。

レプリケーションのアルゴリズム

S0 と利用可能なメモリ容量によってS1がこのメモリ上に使用される場合つだけ使用して、前記二つの等しいサイズに分割され、それはまた、メモリ空間は一度使用、他のメモリに住んでオブジェクトをコピーしますきれい。各回復中にメモリの破片のためのメモリの複雑さを考慮していないそのうちの一つの時間、メモリの割り当ては、単純に、メモリを割り当てるために、シンプルで効率的な動作をスタックポインタの上部に移動するようになっています。

アルゴリズムの欠点は、メモリが元の半分の使用を減らすことができることは明らかであるコピーします。

新世代のガベージコレクションで使用されるアルゴリズムをコピーします

 

クリアラベリングアルゴリズム

マーク - クリア(マーク・スイープ)アルゴリズム名、主に二つの動作、一つのマーカー、他のは明らかであることを示唆しています。

タグは、(例えば:参照カウントアルゴリズム、到達可能性分析アルゴリズム)特定のアルゴリズムに基づいてオブジェクトを使用し続けるであろう、回収することができるメモリ内のどのオブジェクトが示されました。

マークは、直接それを閉鎖し、回復を示し、フラグはまだ立って、それを残して、オブジェクトが使用できることを示しています。

短所

  1. 1.  符号クリア連続ない効率が低いです。
  2. 2.  大量のメモリを生産する破片をクリアした後、

アルゴリズムをソートする - したがって、この残骸の問題は、マークを見て、どのように対処する、に対処しなければなりませんでした。

マーク - 圧縮アルゴリズム

明確なマーカーに基づいてマーク圧縮方式が最適化され、生き残ったオブジェクトは、一端でメモリに圧縮して、ゴミをクリーンアップします。(マークのJavaをラオスの使用は、圧縮方式です)

世代別コレクションアルゴリズム

メモリ内のオブジェクトの生存期間に応じて、メモリはいくつかの部分に分割され、Java仮想マシンのメモリは、一般的に、旧世代と新世代に分けて、新世代のメモリ空間の一般的な割り当ては、新しいオブジェクトが作成されたときにときに、新しい世代いくつかはまだ生きているオブジェクトは、旧世代のメモリに移動された後、大規模なオブジェクトが新しい世代に十分な連続したメモリを見つけることができないときも古い世代で直接作成、ガベージコレクタをリサイクル。

年間、新世代と古い、回復の高周波の新世代が、それぞれの時間は、の低い周波数の古いしばらく回復非常に短い回復時間がかかりますが、比較的長い時間がかかることになるので、GC老後を最小限に抑えるようにする必要があります。

 

なぜ複製アルゴリズムの新世代を使用して、古いマークの使用圧縮、。

ガベージコレクションの休止現象

 

垃圾回收的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以更高效的执行,大部分情况下,会要求系统进如一个停顿的状态。停顿的目的是为了终止所有的应用线程,只有这样的系统才不会有新垃圾的产生。同时停顿保证了系统状态在某一个瞬间的一致性,也有利于更好的标记垃圾对象。因此在垃圾回收时,都会产生应用程序的停顿。

垃圾收集器

什么是Java垃圾回收器

Java垃圾回收器是Java虚拟机(JVM)的三个重要模块(另外两个是解释器和多线程机制)之一,为应用程序提供内存的自动分配(Memory Allocation)、自动回收(Garbage Collect)功能,这两个操作都发生在Java堆上(一段内存快)。某一个时点,一个对象如果有一个以上的引用(Rreference)指向它,那么该对象就为活着的(Live),否则死亡(Dead),视为垃圾,可被垃圾回收器回收再利用。垃圾回收操作需要消耗CPU、线程、时间等资源,所以容易理解的是垃圾回收操作不是实时的发生(对象死亡马上释放),当内存消耗完或者是达到某一个指标(Threshold,使用内存占总内存的比列,比如0.75)时,触发垃圾回收操作。有一个对象死亡的例外,java.lang.Thread类型的对象即使没有引用,只要线程还在运行,就不会被回收。

串行回收器(Serial Collector)

单线程执行回收操作,回收期间暂停所有应用线程的执行,client模式下的默认回收器,通过-XX:+UseSerialGC命令行可选项强制指定。参数可以设置使用新生代串行和老年代串行回收器

年轻代的回收算法(Minor Collection)
把Eden区的存活对象移到To区,To区装不下直接移到年老代,把From区的移到To区,To区装不下直接移到年老代,From区里面年龄很大的升级到年老代。 回收结束之后,Eden和From区都为空,此时把From和To的功能互换,From变To,To变From,每一轮回收之前To都是空的。设计的选型为复制。

年老代的回收算法(Full Collection)
年老代的回收分为三个步骤,标记(Mark)、清除(Sweep)、合并(Compact)。标记阶段把所有存活的对象标记出来,清除阶段释放所有死亡的对象,合并阶段 把所有活着的对象合并到年老代的前部分,把空闲的片段都留到后面。设计的选型为合并,减少内存的碎片。

并行回收

并行回收器(ParNew回收器)


并行回收器在串行回收器基础上做了改进,他可以使用多个线程同时进行垃
圾回收,对于计算能力强的计算机而言,可以有效的缩短垃圾回收所需的尖
际时间。
ParNew回收器是一个工作在新生代的垃圾收集器,他只是简单的将串行回收
器多线程快他的回收策略和算法和串行回收器一样。
使用XX:+UseParNewGC 新生代ParNew回收器,老年代则使用市行回收器
ParNew回收器工作时的线程数量可以使用XX:ParaleiGCThreads参数指
定,一般最好和计算机的CPU相当,避免过多的栽程影响性能。

并行回收集器(ParallelGC)

老年代ParallelOldGC回收器也是一种多线程的回收器,和新生代的
ParallelGC回收器一样,也是一种关往吞吐量的回收器,他使用了标记压缩
算法进行实现。
-XX:+UseParallelOldGC 进行设置
-XX:+ParallelCThread也可以设置垃圾收集时的线程教量。

 

并CMS(并发GC)收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于“标记-清除”算法实现的,整个收集过程大致分为4个步骤:

①.初始标记(CMS initial mark)

②.并发标记(CMS concurrenr mark)

③.重新标记(CMS remark)

④.并发清除(CMS concurrent sweep)

     其中初始标记、重新标记这两个步骤任然需要停顿其他用户线程。初始标记仅仅只是标记出GC ROOTS能直接关联到的对象,速度很快,并发标记阶段是进行GC ROOTS 根搜索算法阶段,会判定对象是否存活。而重新标记阶段则是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间会被初始标记阶段稍长,但比并发标记阶段要短。

     由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以整体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

CMS收集器的优点:并发收集、低停顿,但是CMS还远远达不到完美,器主要有三个显著缺点:

CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。CMS默认启动的回收线程数是:(CPU数量+3) / 4。

CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure“,失败后而导致另一次Full  GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序的运行自热会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理它们,只好留待下一次GC时将其清理掉。这一部分垃圾称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,
即需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分内存空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间时就会被激活,也可以通过参数-XX:CMSInitiatingOccupancyFraction的值来提供触发百分比,以降低内存回收次数提高性能。要是CMS运行期间预留的内存无法满足程序其他线程需要,就会出现“Concurrent Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置的过高将会很容易导致“Concurrent Mode Failure”失败,性能反而降低。

最后一个缺点,CMS是基于“标记-清除”算法实现的收集器,使用“标记-清除”算法收集后,会产生大量碎片。空间碎片太多时,将会给对象分配带来很多麻烦,比如说大对象,内存空间找不到连续的空间来分配不得不提前触发一次Full  GC。为了解决这个问题,CMS收集器提供了一个-XX:UseCMSCompactAtFullCollection开关参数,用于在Full  GC之后增加一个碎片整理过程,还可通过-XX:CMSFullGCBeforeCompaction参数设置执行多少次不压缩的Full  GC之后,跟着来一次碎片整理过程。

G1回收器

G1回收器(Garbage-First)实在]dk1.7中提出的垃圾回收器,从长期目标来看是为了取
代CMS回收器,G1回收器拥有独特的垃圾回收策略,G1属于分代垃圾回收器,区分
新生代和老年代,依然有eden和from/to区,它并不要求整个eden区或者新生代、老
年代的空间都连续,它使用了分区算法。
并行性: G1回收期间可多线程同时工作。
井发性G1拥有与应用程序交替执行能力,部分工作可与应用程序同时执行,在整个
GC期间不会完全阻塞应用程序。
分代GC:G1依然是一个分代的收集器,但是它是非两新生代和老年代一杯政的杂尊。
空间基理,G1在国收过程中,不会微CMS那样在若千tacAy 要进行碎片整理。
G1
来用了有效复制对象的方式,减少空间碎片。
利得程,用于分区的原因,G可以贝造取都分区城进行回收,帽小了国收的格想,
提升了性能。
使用.XXX:+UseG1GC 应用G1收集器,
Mills指定最大停顿时间
使用-XX:MaxGCPausel
设置并行回收的线程数量
使用-XX:ParallelGCThreads

Tomcat配置调优测试

Jmeter压力测试工具

JMeter是一款在国外非常流行和受欢迎的开源性能测试工具,像LoadRunner 一样,它也提供了一个利用本地Proxy Server(代理服务器)来录制生成测试脚本的功能,但是这个功能并不好用。所以在本文中介绍一个更为常用的方法——使用Badboy录制生成 JMeter 脚本。

简单的介绍一下BadboyBadboy是一款不错的Web自动化测试工具,如果你将它用于非商业用途,或者用于商业用途但是安装Badboy 的机器数量不超过5台,你是不需要为它支付任何费用的。也许是一种推广策略,Badboy提供了将Web测试脚本直接导出生成JMeter 脚本的功能,并且这个功能非常好用,也非常简单。你可以跟着下面的试验步骤来迈出你在开源世界的第一步。

1.      通过Badboy的官方网站下载Badboy的最新版本;

2.      安装Badboy。安装过程同一般的Windows 应用程序没有什么区别,安装完成后你可以在桌面和Windows开始菜单中看到相应的快捷方式——如果找不到,可以找一下Badboy安装目录下的Badboy.exe 文件,直接双击启动Badboy

3.      启动Badboy,你可以看到下面的界面。

在地址栏(图中红色方框标注的部分)中输入你需要录制的Web应用的URL——这里我们以http://www.yahoo.com 为例,并点击GO 按钮开始录制。如果你用过LoadRunner之类的商业工具,对于这个操作一定不会陌生吧 ^_^

4.      开始录制后,你可以直接在Badboy内嵌的浏览器(主界面的右侧)中对被测应用进行操作,所有的操作都会被记录在主界面左侧的编辑窗口中——在这个试验中,我们在Yahoo的搜索引擎中输入 JMeter 进行搜索。不过你将看到,录制下来的脚本并不是一行行的代码,而是一个个Web对象——这就有点像LoadRunner的VuGen中的Tree View视图;

5.      录制完成后,点击工具栏中的“停止录制”按钮,完成脚本的录制;

6.      选择“File -> Export to JMeter”菜单,填写文件名“login_mantis.jmx”,将录制好脚本导出为JMeter脚本格式。也可以选择“File -> Save”菜单保存为Badboy脚本;

7.      启动JMeter并打开刚刚生成的测试脚本。

也许你已经急不可待的准备开始尝试着用JMeter处理你手头的工作了^_^ 在下面的几节,我将继续为大家介绍如何在 JMeter 中完成一个测试场景的设置和JMeter测试结果分析入门,以及如何参数化JMeter脚本。

当然,如果你的动手能力很强,几分钟你就可以熟悉这些内容。不过还是请允许我一点点由浅入深的来帮大家完成“JMeter从入门到精通”的过程。我相信在这个过程中你将会了解到更多有关性能测试的知识和经验,甚至包括一些LoadRunner等商业测试工具所无法提供给你的经验。

测试串行吞吐量

-XX:+PrintGCDetails -Xmx32M -Xms32M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M
//项目启动GC回收6次 吞吐量390

扩大堆的内存

-XX:+PrintGCDetails -Xmx512M –Xms32M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M
GC回收6次  445
//结论 最大内存越大,吞吐量越高。

调整初始堆

-XX:+PrintGCDetails -Xmx512M –Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M
//GC回收0次  492

并行回收(UseParNewGC)

-XX:+PrintGCDetails -Xmx512M –Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParNewGC
-XX:PermSize=32M
//GC回收0次 吞吐量452

并行合并回收(UseParallelGC)

-XX:+PrintGCDetails -Xmx512M -Xms256M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:ParallelGCThreads=8
-XX:PermSize=32M
//GC回收0次 吞吐量

调优总结

初始堆值和最大堆内存内存越大,吞吐量就越高。

最好使用并行收集器,因为并行手机器速度比串行吞吐量高,速度快。

设置堆内存新生代的比例和老年代的比例最好为1:2或者1:3。

减少GC对老年代的回收。

 

おすすめ

転載: www.cnblogs.com/hongmoshui/p/10986443.html