みんな大好きJava gc入門 【前編】
GCは、ガベージコレクションの略で、日本語だ
と、ごみ収集の意味ですね。
で、コンピューター業界で言う、ごみ収集とい
うのは、ずばり、メモリのごみ掃除屋さんを示
します。
メモリ
GCとか、勉強する価値あるの?
考えなくて良いために、GCあるんちゃうん?
はい、例えばJavaで、頼まれた設計書の内容を
ただ記述するだけのコーダーのような人には必
要ないでしょう。
ただ、もし、Javaプログラマーとして、ご飯を
食べて生きたいと思っているなら、ちょっと
待って欲しい。
プロのJavaプログラマとして、
GCすら知らない!!
まして、GCに対するチューニングも、問題発生
時の対処も出来ないというのは、Javaプログラ
マと果たして、言えるのでしょうか?
いや、言えない!!
私の感覚だと、プロジェクト3つくらいやれば、
1つくらい、GCの問題にぶち当たってるイメージ
です。
また、C# の話とはなりますが、最近チラッとみ
た、優秀なエンジニアたちの呟きをご覧くださ
い。
このように、優秀なエンジニアは、
GCを制す必要があるのです!!
GCを制すものはJavaを制す!!
GCの必要性について、わかったところで、
引き続き、素晴らしきGCの世界を
勉強していきましょう!
C言語でのメモリの利用について見てみよう。
char *str;
/* 文字列のためのメモリを確保 */
Str = (char *)malloc(100);
/* 文字列を入力(abc) */
gets(str);
/* 文字列の表示 */
puts(str);
/* メモリの解放 */
free(str);
C言語でのメモリの利用について見てみよう。
char *str;
/* 文字列のためのメモリを確保 */
Str = (char *)malloc(100);
/* 文字列を入力(abc) */
gets(str);
/* 文字列の表示 */
puts(str);
/* メモリの解放 */
free(str);
メモリ
サイズ:100
内容:空
C言語でのメモリの利用について見てみよう。
char *str;
/* 文字列のためのメモリを確保 */
Str = (char *)malloc(100);
/* 文字列を入力(abc) */
gets(str);
/* 文字列の表示 */
puts(str);
/* メモリの解放 */
free(str);
メモリ
サイズ:100
内容:空
メモリ
サイズ:100
内容:abc
C言語でのメモリの利用について見てみよう。
char *str;
/* 文字列のためのメモリを確保 */
Str = (char *)malloc(100);
/* 文字列を入力(abc) */
gets(str);
/* 文字列の表示 */
puts(str);
/* メモリの解放 */
free(str);
メモリ
サイズ:100
内容:空
メモリ
サイズ:100
内容:abc
メモリ
サイズ:100
abc
というわけで、C言語など、GCのない世界では、
自前で、メモリの管理を行っていた。
これによって、C言語er の人たちは日々、以下
の問題を抱えていた。
・メモリリーク (メモリ解放忘れ)
・メモリの二重解放 (掃除のやりすぎ)
・メモリアクセス違反 (メモリ管理大失敗)
そこで、GCですよ!!!
メモリ
GCさえあれば、もう、
面倒なメモリ管理から
今すぐ解放!!
致命的な不具合とも
おさらば!!
金運も上昇!!!
ツイて、ツイて、
ツキまくーる!!!!
メモリ
※効果には個人差があります
では、やっとこさ、そろそろ本題となる、
GCは一体どんなお仕事をしているのか??
・・・、というのを
Javaを用いて、順に見ていこう!
// 人間クラス
class Human {
int hp;
int mp;
public Human(int hp, int mp) {
this.hp = hp;
this.mp = mp;
}
public work(int time) {
hp -= time * 10000;
}
}
// 適当なメソッド
public void foo() {
// ① 人間生成
Human yamada = new Human(65535, 1);
// ② 人間働く(24時間)
yamada.work(24);
// ③ メソッド終了
}
// 人間クラス
class Human {
int hp;
int mp;
public Human(int hp, int mp) {
this.hp = hp;
this.mp = mp;
}
public work(int time) {
hp -= time * 10000;
}
}
// 適当なメソッド
public void foo() {
// ① 人間生成
Human yamada = new Human(65535, 1);
// ② 人間働く(24時間)
yamada.work(24);
// ③ メソッド終了
}
スタックメモリ
変数
yamada
ヒープメモリ
① 人間生成
Humanオブジェクト
Hp : 65535
MP : 1
参照
// 人間クラス
class Human {
int hp;
int mp;
public Human(int hp, int mp) {
this.hp = hp;
this.mp = mp;
}
public work(int time) {
hp -= time * 10000;
}
}
// 適当なメソッド
public void foo() {
// ① 人間生成
Human yamada = new Human(65535, 1);
// ② 人間働く(24時間)
yamada.work(24);
// ③ メソッド終了
}
スタックメモリ
変数
yamada
ヒープメモリ
① 人間生成
Humanオブジェクト
Hp : 65535
MP : 1
参照
スタックメモリ
変数
yamada
ヒープメモリ
② 人間働く(24時間)
Humanオブジェクト
Hp : -174465
MP : 1
参照
// 人間クラス
class Human {
int hp;
int mp;
public Human(int hp, int mp) {
this.hp = hp;
this.mp = mp;
}
public work(int time) {
hp -= time * 10000;
}
}
// 適当なメソッド
public void foo() {
// ① 人間生成
Human yamada = new Human(65535, 1);
// ② 人間働く(24時間)
yamada.work(24);
// ③ メソッド終了
}
スタックメモリ
変数
yamada
ヒープメモリ
① 人間生成
Humanオブジェクト
Hp : 65535
MP : 1
参照
スタックメモリ
変数
yamada
ヒープメモリ
② 人間働く(24時間)
Humanオブジェクト
Hp : -174465
MP : 1
参照
スタックメモリ
変数
yamada
ヒープメモリ
③ メソッド終了
Humanオブジェクト
Hp : -174465
MP : 1
参照
// 人間クラス
class Human {
int hp;
int mp;
public Human(int hp, int mp) {
this.hp = hp;
this.mp = mp;
}
public work(int time) {
hp -= time * 10000;
}
}
// 適当なメソッド
public void foo() {
// ① 人間生成
Human yamada = new Human(65535, 1);
// ② 人間働く(24時間)
yamada.work(24);
// ③ メソッド終了
}
スタックメモリ
変数
yamada
ヒープメモリ
① 人間生成
Humanオブジェクト
Hp : 65535
MP : 1
参照
スタックメモリ
変数
yamada
ヒープメモリ
② 人間働く(24時間)
Humanオブジェクト
Hp : -174465
MP : 1
参照
スタックメモリ
変数
yamada
ヒープメモリ
③ メソッド終了
Humanオブジェクト
Hp : -174465
MP : 1
参照
出番やでー
参照が誰からもされていないので、
おばちゃん(GC)から「ごみ」と認識され、
掃除対象となる
不必要なメモリの基本的な判断方法は、今伝えたものと
なります。では、次に、具体的な手法についてみてみま
しょう!
メモリをお掃除する方法(アルゴリズム)で、最も古く、
そして、基本となる手法は、
「マーク&スイープ GC」
といわれるものになります。
【マークフェーズの概念】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
【マークフェーズの概念】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
参照されているオブジェクトをマーク
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
【GCルートについて】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
この例のように、参照を辿るス
タート地点になるものをGCルート
というよ。
【GCルートについて】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
この例のように、参照を辿るス
タート地点になるものをGCルート
というよ。
GCルートとなるもの
・スレッドのスタック
・JNI
・ファイナライザキュー
・スタティック変数領域
【スイープフェーズの概念】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
ヒープメモリ全てをサーチし、マークがついてないオブジェクトを
解放します。あと、ついでに、マークを消してきます。
【スイープフェーズの概念】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
ヒープメモリ全てをサーチし、マークがついてないオブジェクトを
解放します。あと、ついでに、マークを消してきます。
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトC】
マークアンドスイープGCのメリデリ
【メリット】
実装がシンプルで簡単
参照先を書き換えることがない
【デメリット】
断片化が発生しやすい(フラグメンテーション)
メモリの生成が遅い(アロケーション)
Stop the World の時間が長い
次に、マークアンドスイープ GCの弱点をカバーできる、
「コピー GC」
を紹介します。
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
メモリ空間を2つ分用意し、
そのうち半分のみを利用
From領域
To領域
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
メモリ空間を2つ分用意し、
そのうち半分のみを利用
ルートから辿って、利用されている
オブジェクトをTo領域にコピーします
From領域
To領域
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
From領域
To領域
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトC】
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
メモリ空間を2つ分用意し、
そのうち半分のみを利用
ルートから辿って、利用されている
オブジェクトをTo領域にコピーします
From領域
To領域
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
From領域
To領域
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトC】
コピーする際、参照を
付け替えます。
スタックメモリ
Aへの参照
ヒープメモリ
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトB】 【オブジェクトC】
To領域
From領域
【オブジェクトA】
オブジェクトCへの参照
【オブジェクトC】
FromとTo領域を入れ替えます
コピーGCのメリデリ
【メリット】
Stop the World の時間が短い
メモリの生成が早い(アロケーション)
断片化が発生しない(フレグメンテーション)
【デメリット】
ヒープの使用効率が悪い
参照の書き換えが発生
Javaでは、初期からVer1.4までの間、今紹介した、
「マークアンドスイープGC」と「コピーGC」のメリット
を掛け合わせた「世代別GC」が採用されていました。
マークアンドスイープGC + コピーGC = 世代別GC
・・・というわけで、
長くなってきたので、今回はここまで。
というわけで、長くなってきたので、今回はここまで。
次回は・・・。
Javaで利用された世代別GCとは?
これが、世代別GC・・・
圧倒的じゃないか、我がメモリ管理は
ストップ・ザ・ワールド!!
そして、処理は動き出す・・・
私は念によって、時を止めずに
GCすることに成功した
・・・その名もコンカレントGC
そして、世界はG1GCへと辿りついた・・・
というわけで、長くなってきたので、今回はここまで。
次回は・・・。
Javaで利用された世代別GCとは?
・・・というわけで、
長くなってきたので、今回はここまで。
リクエスト多ければやります・・・。
ご清聴ありがとうございました。

More Related Content

PDF
Java仮想マシンの実装技術
PDF
C++ マルチスレッドプログラミング
PPTX
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
PDF
中3女子が狂える本当に気持ちのいい constexpr
PDF
規格書で読むC++11のスレッド
PDF
C++ マルチスレッド 入門
PDF
Javaはどのように動くのか~スライドでわかるJVMの仕組み
PDF
JSRとJEPとJBSの見方や調べ方について
Java仮想マシンの実装技術
C++ マルチスレッドプログラミング
9/14にリリースされたばかりの新LTS版Java 17、ここ3年間のJavaの変化を知ろう!(Open Source Conference 2021 O...
中3女子が狂える本当に気持ちのいい constexpr
規格書で読むC++11のスレッド
C++ マルチスレッド 入門
Javaはどのように動くのか~スライドでわかるJVMの仕組み
JSRとJEPとJBSの見方や調べ方について

What's hot (20)

PDF
Constexpr 中3女子テクニック
PPTX
冬のLock free祭り safe
PDF
JVMのGCアルゴリズムとチューニング
PDF
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
PDF
今日からできる!簡単 .NET 高速化 Tips
PDF
マーブル図で怖くないRxJS
PPTX
MQ入門
PPTX
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
PDF
負荷テストを行う際に知っておきたいこと 初心者編
PDF
マルチテナントのアプリケーション実装〜実践編〜
PDF
Djangoのエントリポイントとアプリケーションの仕組み
PPTX
SDL2の紹介
PDF
組み込み関数(intrinsic)によるSIMD入門
PPTX
はじめての datadog
PPTX
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
PDF
できる!並列・並行プログラミング
PDF
Akkaとは。アクターモデル とは。
PPTX
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
PDF
/etc/network/interfaces について
PPTX
Effective Modern C++ 勉強会 Item 22
Constexpr 中3女子テクニック
冬のLock free祭り safe
JVMのGCアルゴリズムとチューニング
大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
今日からできる!簡単 .NET 高速化 Tips
マーブル図で怖くないRxJS
MQ入門
JEP280: Java 9 で文字列結合の処理が変わるぞ!準備はいいか!? #jjug_ccc
負荷テストを行う際に知っておきたいこと 初心者編
マルチテナントのアプリケーション実装〜実践編〜
Djangoのエントリポイントとアプリケーションの仕組み
SDL2の紹介
組み込み関数(intrinsic)によるSIMD入門
はじめての datadog
MVPパターンによる設計アプローチ「あなたのアプリ報連相できてますか」
できる!並列・並行プログラミング
Akkaとは。アクターモデル とは。
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
/etc/network/interfaces について
Effective Modern C++ 勉強会 Item 22
Ad

みんな大好きJava gc入門 【前編】