JVM学習 - ガベージコレクションGC(学習プロセス)

JVM学習 - ガベージコレクション(GC)

2020年2月19日午前六時03分56秒スタートソースを学習、ガベージコレクションを学習(JVMの先生張ロングコース)

JVMメモリデータ領域の知識レビュー

ガベージコレクションを学習する前に、内部JVMのメモリ領域の詳細な理解を持っています。関連するメモリ領域の内容の事前知識が審査し、まとめた、ガベージコレクションを学習するための基礎を築きます。

画像-20200219060429726

灰色の領域は、スレッドが共有されています

白い領域は、単離されたスレッドであります

画像-20200219064036596

画像-20200219064120088

画像-20200219064229291

参照4バイト、ヌルオブジェクトの8バイト。

メソッドを実行した後、対応するスタックスタック変数は直ちに回復したが、GCまでヒープオブジェクトを回収しました。

JVMのガベージコレクション(ガベージコレクション)

理論的な知識

JVMのガベージコレクション(GC)モデル

  1. ゴミ判定アルゴリズム
  2. GCアルゴリズム
  3. ガベージコレクタの実装と選択

ゴミ判定アルゴリズム

  1. 参照カウントアルゴリズム(参照カウント)
  2. ルート検索アルゴリズム(GCのルーツをトレース)

参照カウントアルゴリズム

画像-20200219064625169

サイクルの終わりで参照問題対象:B、B、および参照Aに参照 でも外部参照なし。しかし、それは状態となっているので、それを復元することはできません。

画像-20200219064807017

もちろん、彼はまだ他の手段によって、この欠点を回避することができます。

ルート検索アルゴリズム

画像-20200219070328494

画像-20200219070437201

メソッド地区

画像-20200219070745942

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

  1. マーク - スイープアルゴリズム(マークスイープ)
  2. マーク - 照合アルゴリズム(マーク・コンパクト)
  3. レプリケーションアルゴリズム(コピー)
  4. 世代アルゴリズム(世代別):このアルゴリズムを使用して、ほとんどすべての仮想マシン

なぜマルチユースそれの新世代のコピーアルゴリズムを?JavaのJavaオブジェクトのほとんどがあるので登録は消滅します。非常にリサイクルすることができません。旧の長いライフサイクル、コピーアルゴリズムを使用すると便利ではありません。

だから、古いのは明らかにマークされ、ラベルされた照合アルゴリズムの使用します

マーク - 明確なアルゴリズム(マークスイープ)

画像-20200219071343749

マーク - 明確なアルゴリズム:以下のように概略が行われます

これらのオブジェクトは、次の対象となります

image-20200219072023671

ランタイムスタックの仮想マシン・スタックは、検索アルゴリズムのルートへの入り口です

image-20200219072122102

まずマーク

image-20200219072157821

F. - J間の循環参照 しかし、DG -FJMが出て回復することになっています。グリーンも保持されます。

手順を実行した後、以下に示されています

クリア再び

image-20200219072245947

image-20200219072301392

コピー(コピー)コレクションアルゴリズム

image-20200219072438309

シンプルで効率的な操作:しかし:高価なオリジナルの一般的にメモリを減らす必要があります。

image-20200219072606909

今、主に回復するために使用新生代を

image-20200219073336674

在老年代中,一般不能直接选用这种算法。(因为老年代的存活率高 )

复制搜集算法的示意图

  1. 把A- C=复制

image-20200219073521882

把相互引用的都给复制

image-20200219073711606

余下的没有被复制,会被连锅端掉

image-20200219073746128

复制搜集算法优点

image-20200219073803923

标记-整理算法

image-20200219073918760

如下为执行示意图

标记移动。腾出来连续的空间。没有内存碎片。就是有点慢。

image-20200219073959046

image-20200219074030501

分代收集算法(Generational Collecting)

image-20200219074425744

新生代 和 老年代 的定义

新生代:部分刚新生的对象,没有用的

老年代:经历多次垃圾回收,还会保留

image-20200219074816247

JVM6时候的参考(现在已经没有永久代了)

image-20200219074836178

image-20200219075017841

为什么说只会浪费百分之十呢,这里二娃给我讲述的

这次 设置了2个Survivor是非常巧妙的。第一次的时候,8+1 被使用。复制完之后。放入另外一个Survivor。然后下一次的时候。8+另外一个1,把对象复制到1上。所以就完成了,轮流替换。每次被闲置的就会只有一个占用百分之10的Survivor来准备接受要复制的对象。over。

image-20200219075635735

JVM启动的时候可以根据程序的需要,选择一定的需求所对应的垃圾收集器和对应的垃圾收集算法。

image-20200219075742489

内存相关概念

内存结构

image-20200219075826778

内存分配

image-20200219080003520

内存回收

image-20200219080025676

强引用,软引用,弱引用,虚引用

image-20200219080154476

软引用:内存不够的时候,一会被会GC,长期不用也会被收集

垃圾收集算法

image-20200219080244760

黄色区域应用在年轻代

灰色区域应用在老年代

GC触发的时机

image-20200219080326960

尽量避免对Full GC的使用,因为全局GC调用的时候,会停滞所有的义务代码执行。

MinorGC是一定会有的。

垃圾回收器

垃圾回收器理论分析

没有万能的垃圾回收器,交互性和吞吐率是不兼容的,没有银弹

image-20200219080629770

垃圾收集器的“并行”和“并发”

image-20200219081106164

让用户线程处于等待状态是一个很恐怖的事情。

收集器

Serial收集器

STW(Stop The World) 暂停所有的工作线程

虚拟机运行Client模式下的默认收集器

image-20200219081155185

image-20200219081227092

单线程的GC。

ParNew收集器

Serial的多线程版本。其他都一样

image-20200219081416624

image-20200219081532679

Parallel Scavenge收集器

image-20200219081637673

允许较长较长时间的STW。

Serial Old收集器

image-20200219081722260

Parallel Old收集器

image-20200219081731864

image-20200219081742646

CMS收集器:实现非常复杂的收集器

image-20200219094602469

image-20200219094637936

image-20200219094655006

image-20200219094720256

image-20200219094735395

综上,PPT 都需要自己详细读读。

再次回顾一下JVM的内存数据区域的分配情况

image-20200219092857424

  1. Oracle的HotSpot虚拟机,将 java虚拟机方法栈和本地方法栈放在同一个地方
  2. 程序计数器是唯一一个没有要求说必须要使用GC垃圾回收的地方。
  3. 白色的地方是线程独有的

总结

  • 垃圾判断算法
    • 引用计数算法
    • 根搜索算法
  • 垃圾回收GC算法(常见的)
    • 标记-清除算法
    • 标记-整理算法
    • 复制算法(8-1-1)
    • 分代算法(综合前面几种,针对不同的类型,采用不同的算法)
  • 垃圾收集器
    • Serial
    • ParNew
    • Parallel Scavenger (PS (jdk1.8默认的新生代垃圾收集器))
    • Parallel Old(ParOld jdk1.8默认的老年代垃圾收集器)
    • Serial Old
    • CMS

Java内存泄露的经典原因

  1. 对象定义在错误的范围(Wrong Scope)
  2. 异常(Exception)处理不当
  3. 集合数据管理不当

对象定义在错误的范围

image-20200219095147567

从成员变量 移动到 局部变量。 (布局就不一样了。变量会被及时回收)

异常处理不当

image-20200219095332632

异常处理的不到位,关闭流的操作,应该放置在finally里面。

image-20200219095408581

集合数据管理不当

image-20200219095427055

垃圾回收日志(GC Log)

上案例:

image-20200219100059547

这里需要注意点是:数组是原生数据类型。 数组里面的默认值都是0。如果是引用类型的数组,里面的值都为null。

程序初始:

平淡无奇

image-20200219100226243

输出结果:平淡无奇:

image-20200219100816679

接下来添加一定的JVM参数,进行启动,就变得大不一样

JVM参数加 -verbise:gc : 添加垃圾回收GC的详细信息

JVM参数加 Xms20M Xmx20m:分别表示堆容量的初始值和最大值,一般都设置为一样。固定位20M

JVM参数加-XMn10M:表示新生代的容量大小为10M

JVM参数加-XX:+PrintGCDetails:打印GC的详细信息

JVM参数加-XX:SurvivorRatio=8:表示Even空间和Survivor的比例是8:1:1

image-20200219100657109

运行结果:只有GC详情,但是未执行GC

这东西都是:-XX:+PrintGCDetails 打印的,还没有展现GC、

在程序中,再加入一行 代码,再加一个数组(大小就到达GC临界点)

image-20200219101210887

运行结果:GC就出来了

image-20200219101121573

image-20200219101313534

随着程序的变化,内存空间的修改。会导致不同的打印结果出现。

GC:表示 minor GC ,后面数据的含义和格式

​ Allocation Failure:分配失败

​ PSYoungGen:年轻代 PS(Parallel Scavenger 收集器)。

​ 执行前-执行后(总容量):(7694k->624k(9216k))

​ 执行GC之前堆的大小-执行后的存活对象的大小(堆的大小):(5656k->4728k(19456k))

image-20200219102735659

4104k对应的,正好是老年代新增的 大小。(从新生代释放出来,进入老年代)

Full GC 会导致程序暂停 (2,2,2,2 会出现Full GC, 2,2,3,3 反而不会进入Full GC)

没进入Full GC的原因:当新生代已经无法容纳要生成的对象的时候,直接放入老年代

验证的概念如下:GC的触发时机

image-20200219101421689

对于网上的文章或者概念,还有书本等等。里面的内容都是不确定是对的,唯一能验证概念的,就是通过代码,通过数据去看结论。

JVM参数

image-20200219094720256

image-20200219094735395

java -XX:+PrintCommandLineFlags -version :输出启动参数和java版本

image-20200219110007233

-XX:+UseParallelGC : 默认使用的GC是 Parallel

-XX:PretenureSizeThreshold=4194304:大小阈值设置,设置超过多大值时直接在老年代进行分配。

超过这个值之后,就不会在新生代去创建,直接进行入老年代

设置好上述参数,然后执行下面程序:

image-20200219112038982

但是:并不是上面的参数结论的作用。所以,一般结论正确与否,还是需要通过代码来确定正确性。

是因为:上述概念是需要使用 Serial 垃圾回收器。

所以再加一个参数:-XX:+UseSerialGC设置项目启动之后使用的GC是Serial垃圾回收器

image-20200219113314931

老年代占用5M:直接就是程序定义的对象的大小:说明直接进入老年代。

使用可视化工具查看垃圾回收

image-20200219114409701

这里可视化工具提供的手动按钮是 Full GC (System.gc())

image-20200219114515452

image-20200219114528973

关于System.gc()的补充,我们手动调用gc或者自己执行gc方法的时候,我们只是告诉了JVM需要执行垃圾回收,但是至于什么时候回收,是由JVM决定的。

如果我们不告诉JVM需要GC的话,只有在创建新的对象的时候才有可能去校验是否需要垃圾回收。因为只有在创建对象的时候会导致堆内存的增加。

这就是System.get()方法存在的意义和价值:在没有对象创建的时候触发垃圾回收。

jmc查看的可视化

image-20200219114902217

image-20200219115251845

FromSurvivor和ToSurvivor的角色的切换

如果频繁切换,那么会通过一定的算法转移到老年代。

-XX:MaxTenuringThreshold=5:在可以自动调节对象晋升(Promote)到老年代阈值的GC中设置该阈值的最大值。

设置可以晋升到老年代的最大存活年龄。该参数的默认值为15,CMS中默认值为6,G1中默认为15(在JVM汇总,该数值是由4个bit来表示的,所以最大值为1111,即15)

-XX:+PrintTenuringDistribution:打印出年龄为n的字节对象

经历了多次GC后,存货的对象会在FromSurvivor和ToSurvivor的角色之间来回切换。而这里面的一个前提则是这两个空间有足够的大小来存放这些数据,在这些算法中。会计算每个对象年龄的大小,如果达到某个年龄后发现总大小已经大于了Survivor空间的50%,那么这时候就需要调整阈值,不能再继续等到默认的15此GC后才完成晋升,因为这样会导致Survivor空间不足,所以需要调整阈值,让这些存货对象尽快完成晋升。

Survivor空间不足是很严重的。

image-20200219121330920

image-20200219121345626

运行结果:

image-20200219121422183

threshold的动态调整

image-20200219130642857

image-20200219130751220

这个时候运行,没有问题。

接下来添加JVM参数

XX:TargetSurviorRatio=60 :占据百分之60,会重新计算阈值

XX:+PrintGCDateStamps:打印JVM运行的时间戳

XX:+UseConcMarkSweepGC: 老年代使用CMS

XX:+UserParNewGC:新生代使用ParNew

XX:MaxTenuringThreshold=3:最大年龄为3,就得去老年代了

image-20200219131136864

运行结果

image-20200219131207830

image-20200219132004058

image-20200219132049706

这里,下面的图,只有age=1的,说明,age=1,=2,=3的已经被全部放入老年代当中。

image-20200219131906826

枚举根节点

image-20200219154558522

OopMap数据结构

安全点: Safepoint

image-20200219154756567

セキュリティのポイント:プログラムの実行は、それが一時停止に安全な地点に到達したときにのみ、GCを開始ダウンすべての場所で停止することはできません。

image-20200219154809669

image-20200219155750717

タイプの割り込みを盗み:JVM割り込み

アクティブブレイク:投票所の看板と安全ポイントが一致。今、彼らは自分自身を中断します。

image-20200219160034945

セキュリティゾーン

image-20200219160331233

image-20200219161026460

安全な地域

詳細CMSガベージコレクタ

CMSガベージコレクタ仕上げ学校の後、あなたはG1のガベージコレクタについて学ぶために大きな努力を必要とします。

ストーリー:人々のCMSの研究は新しい人々がC ++ソースコードを読むことができないか、左。

CMS:並行マークスイープ並行マーク・クリア

image-20200219162027113

同時の意味:ガベージコレクションのスレッドが同時にビジネスユーザーやスレッドを実行することができます。

マークとクリア:説明CMSが完了するのマークとスイープを使用することです。

フラグ:フラグはまだ生き状態の一部であるオブジェクトです。オブジェクトをクリアする必要がどのようなものです。

クリア:クリアゴミを離れオブジェクト。

image-20200219162510850

初期タグ:

同時マーク:

ラベル変更:一部による同時ユーザスレッドが変更の結果を操作し続ける補正期間に。

明確な同時:

CMSは動作ステップをコレクタ:

image-20200219162739106

初期マーク:STW、ない、スレッド

同時マーク:ユーザーが同時に実行できるスレッド

再ラベル:STW、ない、マークを

同時クリーンアップ:ユーザーが同時に実行できるスレッド

リセットスレッド:初期状態への復帰

CMSコレクタの長所と短所

利点:

image-20200219163126923

一時停止:それはユーザスレッドポーズを指し、

短所:

image-20200219163151757

スペース割り当て保証:新世代は、古い年間の保証と呼ばれる直接スロー古いのを、受け入れることはできません。

image-20200219163505962

CMSコレクタはステップを収集します。

image-20200219163917024

並行せずに、スレッドを一時停止するようにユーザーにつながります

image-20200219164301754

image-20200219164418340

image-20200219165516791

image-20200219165709071

image-20200219165754883

image-20200219165840708

この目的のために:マークは完了します。次の呼び出しは、アルゴリズムをクリーンアップします。

image-20200219165907894

image-20200219165926941

image-20200219165958257

image-20200219170028823

CMSのガベージコレクタを認識するためのプログラム

プログラムコード

image-20200219174208582

仮想マシンのパラメータ

image-20200219174226957

結果:

image-20200219174525991

おすすめ

転載: www.cnblogs.com/bigbaby/p/12348968.html