技術の犬小屋

Webプログラミングを餌に生きる犬のメモ帳

Posts in the 技術系知識 category

先日,友人に職務経歴を説明するための資料の作成を手伝ってもらった。その際,三層アーキテクチャを用いて資料を作成することで,視覚的に分かりやすい資料が作成できることに気付かされた。今回は三層アーキテクチャの概要と,資料作成における三層アーキテクチャの効果的な活用方法をまとめてみる。
 

三層アーキテクチャとは

クライアントサーバシステムを「プレゼンテーション層」「アプリケーション層」「データ層」の3層に分割して構築したシステム。クライアントおよびサーバの処理を複数の階層に分離して配置することで,ある階層へ変更を加える必要が生じた際にも柔軟に対応できるようなっている。
 
 
上記説明だけでは,よく分からなかったので,補足を説明する。

  • 「プレゼンテーション層」…ユーザインターフェースを提供する。
  • 「アプリケーション層」…アプリケーションのロジックを提供する。ビジネス層とも呼ばれる。
  • 「データ層」…データソースへのアクセス手段を提供する。

 
 
それぞれの層を具体的にソフトウェアと関連付けると以下のようになる。

  • 「プレゼンテーション層」…Webサーバー(Web)。Apache,Nginxなど。
  • 「アプリケーション層」…Applicationサーバー(AP)。CGI,Servlet,mod_php(モジュール)など。
  • 「データ層」…データベース(DB)。MySQL,PostgreSQL,Oracleなど。

 
 
三層アーキテクチャでは,「プレゼンテーション層」が一番ユーザに近く,「データ層」が一番データソースに近い層になっている。
 
三層アーキテクチャの説明
 
これで,三層アーキテクチャの概要を分かっていただけたと思う。
では,これを資料作成に役立てるにはどのように活用すれば良いだろうか。
 
 
友人に指導を受けながら作成した資料では,三層アーキテクチャを用いて,以下のような図を作成した。
 
三層アーキテクチャによる構造の図解
 
「プレゼンテーション層」は,ユーザインターフェースにあたる「画面」単位での記述,「ビジネス層(アプリケーション層)」は,ロジックにあたる「機能」単位での記述,「データ層」では,テーブル(情報)単位での記述を行った。
 
このように三層アーキテクチャを用いて図解することで,複雑なアプリケーション全体の構造を一目で把握することができる。
 
 
以上
 
 
参考
3階層システムとは 〔 三階層システム 〕 【 3-tier system 】 – 意味/解説/説明/定義 : IT用語辞典
@IT:連載:アプリケーション・アーキテクチャ設計入門 第2回 論理アーキテクチャを構成するコンポーネントの設計(プレゼンテーション層編)
Webアプリケーションの仕組み

バイナリについて勉強したので忘れないようにメモしておく。
 

バイナリとは

パソコンで扱うファイルを分類すると,大きく以下の2つに分かれる。

  • テキストファイル
  • バイナリファイル

 

テキストファイルとは

文字を表すデータである。文字コード表に載っているデータだけが書かれているファイルを指す。
 

バイナリファイルとは

テキストファイル以外の全てのファイルを指す。
 

文字コードとは

コンピュータは0と1の組み合わせでしか情報を表現できないので,「文字」の情報を扱うためには,「0と1の組み合わせがどんな文字を表すか」というルールを決めておく必要がある。そのルールを文字コードと呼ぶ。
 
文字コードとは,どんなものかを知る為に,以下に文字コード表の一部を示す。
 
文字コード表
※こちらのページに載っている文字コード表の一部を引用させていただいた。
 
例として,アルファベットの「a」の文字コードを調べてみる。表を見ると,「a」は「6」の行の「1」の列にあることが分かる。よって,この文字コード表では,16進数の「61」というデータが「a」を表している。同様に「a」を2進数で表現する場合は「01100001」となる。
 
※通常,16進数は10進数と間違えないように頭に「0x」と付ける。よって,16進数は「0x61」のように書き表すことができる。
 
文字コードには様々な種類があり,日本語の文字が使える文字コードだけでも,JIS,Shift-JIS,EUC,UTF-16,UTF-8などがある。このような文字コードを作る元になったものとして,ASCII(アスキー)がある。
 

ASCIIと日本語文字コードの関係

ASCIIとは,1963年にアメリカ規格協会(ANSI)が定めた,情報交換用の文字コードの体系である。1967年に国際標準化機構(ISO)で定められた情報交換用符号の国際規格「ISO 646」とほぼ同じものである。7ビットで表現され,128種類のローマ字,数字,記号,制御コードで構成されている。実際にはコンピュータは1文字を8ビット(1バイト)で表現するため,256種類の文字を扱うことができるが,ASCIIが定めていない128文字分の拡張領域には,ンピュータメーカーや国によって異なる文字が収録されている。日本では,拡張領域にカナ文字を収録したコード体系が「JIS X 0201」として規格化されている。
 
この「JIS X 0201」が現存のJIS(日本工業規格)における最も古い文字コードである。JISとは,工業標準化法に基づき,日本工業標準調査会の答申を受けて,主務大臣が制定する工業標準であり,日本の国家標準の一つである。
「JIS X 0201」は,現在では主にShift_JISおよびEUC-JPの一部として用いられており,単独で用いられることはほとんどない。これらの文字コードは JIS X 0208の文字も含んでおり,JIS X 0208にはJIS X 0201にあるほぼすべての文字があるため文字が重複することとなる。この区別のため,JIS X 0201の文字をJIS X 0208の文字の半分の幅で表示することが多い。このため,これらの文字を俗に半角文字,特に片仮名を半角カナと呼ぶ事が多い。
 
文字コードの概要が理解できたところで,以下より,実際にバイナリを読んでみる。
 

実際にバイナリを読んでみる

今回は,Vimのxxdコマンドを使用してテキストをバイナリに変換する。
 

テキストからバイナリに変換する

Vimでテキストを開いた状態で,以下のコマンドを実行することで,バイナリへの変換を行うことができる。
 
:%!xxd
 

バイナリからテキストに変換する

Vimでバイナリを開いた状態で,以下のコマンドを実行することで,テキストへの変換を行うことができる。
 
:%!xxd -r
 

実際にバイナリを読んでみる

以下の内容が記述されたファイルをVimで開き,:%!xxdコマンドを実行する。
 

aaa
bbb
ccc

 
すると,以下のようにテキストがバイナリに変換される。
 
binary
 
上記画像の「0000000:」と「aaa..bbb..ccc..」は視認補助の為の情報なので,バイナリは「6161 610d 0a62 6262 0d0a 6363 630d 0a」の部分である。テキストの「a」はバイナリでは「61」,テキストの「b」はバイナリでは「62」,テキストの「c」はバイナリでは「63」という対応付けが行われている。
「0d」と「0a」は改行コードである。今回はWindowsマシンで作業をしたので,改行コードには「CR+LF」が用いられている。
 

改行コードとは

テキストファイル中で改行を意味する文字コードのことである。正確には,改行してカーソルを行頭に復帰する動作を指示するコードのことを指す。以下の表は改行コードとASCIIコードの対応表である。
 

記号 呼び名,別名 ASCIIコード マッチング
LF ラインフィード(Line Feed),ニューライン(New Line) 0A \n
CR キャリッジリターン(Carriage Return),リターン(Return) 0D \r

 
文字コード体系の種類には依存しないが,もともと「CR」(Carriage Return : 行頭復帰)と「LF」(Line Feed : 改行)の2つのコードが存在していたことから,WindowsではCR+LF,Mac OSではCR,UNIXではLFが使われている。
※Mac OS X以降では,Macの改行コードは「LF」になっている。
 

頻出する制御コード

バイナリファイルの中に頻繁に登場する制御コードとして以下の表に示すものが挙げられる。
 

頻出する制御コードの表
16進数 文字 説明
0x00 NUL 何も書かれていないことを表す空文字。C言語などでは文字列の終端に付けて,これ以降に文字列が続かないことを表す。
0x08 BS バックスペース。
0x09 HT 水平タブ。Tabキーで入力される。tab とは table の意味で,もともと表をつくるための文字である。
0x0A LF ラインフィード。元の意味は「次の行に進める」である。改行コードの一つ。
0x0D CR キャリッジリターン。元の意味は「印字ヘッドを行の先頭に戻す」である。改行コードの一つ。

 
上記は最低限,暗記しておきたい。
 

まとめ

  • ファイルには大きく分けて「テキスト」と「バイナリ」の2つがある
  • 「バイナリ」に文字コードのルールを適用したものが「テキスト」である
  • バイナリを読むには文字コード表を用いる
  • Vimではxxdコマンドによって,「テキスト」と「バイナリ」の相互変換ができる
  • 改行コードは,Windowsが「CR+LF」,Macが「CR」,Unixが「LF」である

 
 
以上
 
 
参考
コンピュータの仕組み ~テキストファイルとバイナリファイル~ | リスティング広告の運用代行ならカルテットコミュニケーションズ
ASCIIとJISローマ字―文字コード入門―
ASCIIとは (アスキーとは) [単語記事] – ニコニコ大百科
エスケープシーケンスとは – IT用語辞典 Weblio辞書
ASCIIとは 〔 アスキーコード 〕 【 US-ASCII 】 – 意味/解説/説明/定義 : IT用語辞典
改行コード – Wikipedia
改行コードの話
vimでバイナリを表示し、値を変更したい – rderaログ

2進数・10進数・16進数の相互変換についてまとめる。専門学生時代に習った知識だが、業務では全く使わないので忘れかけていた。
 

2進数から10進数への変換

 

2進数と10進数の対応表
10進数 2進数
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
10 1010
…… ……

 
上記の表の「2進数の桁が繰り上がるとき」に注目する。以下がそれを抜き出した表である。
 

2進数と10進数の対応表
10進数 2進数
1 00000001
2 00000010
4 00000100
8 00001000
16 00010000
32 00100000
64 01000000
128 10000000

 
上記の対応表を見ると、2進数の桁があがる時の10進数の値が分かる。
 
従って、2進数で「1」となっている桁に対応する10進数の値を合計することにより、2進数から10進数の値を求めることができる。
 
例えば、2進数の「10101010」を10進数に変換する場合、値が128、32、8、2のところでビットが1なので、2進数の「10101010」は10進数では「170」だと分かる。
 
10進数と2進数の対応表
 

10進数から2進数への変換

10進数の数値を「 0 」になるまで「 2 」で割り算していき、その結果の「余りの数」を並べることにより、10進数の値を2進数の値へ変換することができる。
 
例えば、10進数の「28」を2進数に変換すると、以下のようになる。
 

  • 28 / 2 = 14, 余り0
  • 14 / 2 = 7, 余り0
  • 7 / 2 = 3, 余り1
  • 3 / 2 = 1, 余り1
  • 1 / 2 = 0, 余り1

 
足りないビット分は上位のビットから「0」で埋めるので、「00011100」となる。
 

2進数から16進数への変換

2進数の数値を16進数の数値に変換するためには、以下の3つのステップを踏む必要がある。
 

  1. 2進数(8ビット)を4桁(4ビット)ずつに分解する
  2. 分解した数から10進数に変換する
  3. 10進数の値を16進数に変換し、結合する

 
以下では、例として、2進数「00101010」を16進数に変換する場合を考えてみる。
 

2進数を4桁ずつに分解する

2進数「00101010」を「0010」と「1010」に分解する。
 

分解した数から10進数の値を求める

2進数「0010」は10進数「2」となり、2進数「1010」は10進数「10」となる。
 

10進数の値を16進数に変換し、結合する

10進数「2」は16進数「2」となり、10進数「10」は16進数「A」となる。
 
よって、2進数「00101010」は16進数「2A」となる。
 

16進数から2進数への変換

16進数の数値を2進数の数値に変換するためには、2進数から16進数に変換した時と逆のことをする。
これには以下の3つのステップを踏む必要がある。
 

  1. 16進数を1桁ずつに分解する
  2. 分解した値から10進数に変換する
  3. 10進数の値を2進数に変換し、結合する

 
以下では、例として、16進数「2A」を2進数に変換する場合を考えてみる。
 

16進数を1桁ずつに分解する

16進数「2A」を「2」と「A」に分解する。
 

分解した値から10進数に変換する

16進数「2」は10進数「2」となり、16進数「A」は10進数「10」となる。
 

10進数の値を2進数に変換し、結合する

10進数「2」は2進数「0010」となり、10進数「10」は2進数「1010」となる。
 
よって、16進数「2A」は2進数「00101010」となる。
 
 
以上
 
 
参考
ネットワークの勉強をはじめから – 2進数と10進数の変換方法

HTMLの文字参照について

HTMLの文字参照について、覚えきれないのでメモしておく。
特にHTMLのサンプルコードを示す際に使用する、<>はよく使うので覚えておきたい。
 

文字参照一覧

一般的な記号など
文字実体参照 数値文字参照 名称・解説
& &amp; &#38; アンパサンド
¦ &brvbar; &#166; 破断縦線
µ &micro; &#181; マイクロ記号
&permil; &#8240; パーミル
¤ &curren; &#164; 一般通貨記号
&euro; &#128; ユーロ記号
¢ &cent; &#162; セント記号
£ &pound; &#163; ポンド記号
¥ &yen; &#165; 円記号
© &copy; &#169; 著作権記号
® &reg; &#174; 登録商標記号
&trade; &#8482; 商標記号
&uarr; &#8593; 上向き矢印
&rarr; &#8594; 右向き矢印
&darr; &#8595; 下向き矢印
&larr; &#8592; 左向き矢印
&harr; &#8596; 左右両向き矢印
&uArr; &#8657; 上向き二重矢印
&rArr; &#8658; 右向き二重矢印
&dArr; &#8659; 下向き二重矢印
&lArr; &#8656; 左向き二重矢印
&hArr; &#8660; 左右両向き二重矢印
&spades; &#9824; スペードマーク
&clubs; &#9827; クラブマーク
&hearts; &#9829; ハートマーク
&diams; &#9830; ダイヤマーク
ª &ordf; &#170; 女性序数標識
º &ordm; &#186; 男性序数標識
¹ &sup1; &#185; 上付き1
² &sup2; &#178; 上付き2
³ &sup3; &#179; 上付き3
½ &frac12; &#189; 2分の1
¼ &frac14; &#188; 4分の1
¾ &frac34; &#190; 4分の3
約物など
· &middot; &#183; 中点
¡ &iexcl; &#161; 逆さ感嘆符
¿ &iquest; &#191; 逆さ疑問符
&quot; &#34; 引用符
&lsquo; &#8216; 左一重引用符
&rsquo; &#8217; 右一重引用符
&ldquo; &#8220; 左二重引用符
&rdquo; &#8221; 右二重引用符
« &laquo; &#171; 左二重角引用符
» &raquo; &#187; 右二重角引用符
  &nbsp; &#160; 改行なし空白
&emsp; &#8195; “m”幅空白
&ensp; &#8194; “n”幅空白
&thinsp; &#8201; 狭い空白
&mdash; &#8212; “m”幅ダッシュ
&ndash; &#8211; “n”幅ダッシュ
­ &shy; &#173; ソフトハイフン
&bull; &#8226; 行頭文字
&para; &#182; 段落記号
§ &sect; &#167; セクション記号
&dagger; &#8224; ダガー記号
&Dagger; &#8225; ダブルダガー記号
&hellip; &#8230; 省略記号
&loz; &#9674; 菱形
数学記号など
&infin; &#8734; 無限記号
&radic; &#8730; 根号
&minus; &#8722; マイナス
± &plusmn; &#177; プラスマイナス
× &times; &#215; 乗算記号
÷ &divide; &#247; 除算記号
&ne; &#8800; 等しくない
&asymp; &#8776; ほぼ等しい
&cong; &#8773; およそ等しい
> &gt; &#62; 大なり
< &lt; &#60; 小なり
&ge; &#8805; 大なりまたは等しい
&le; &#8804; 小なりまたは等しい
ƒ &fnof; &#402; 関数記号
&prop; &#8733; 比例する
&prime; &#8242; プライム
&Prime; &#8243; 二重プライム
&int; &#8747; 積分記号
&part; &#8706; 偏微分
&nabla; &#8711; ナブラ
&sum; &#8721; 数列の和
&prod; &#8719; 数列の積、直積
&image; &#8465; 虚数
&real; &#8476; 実数
&weierp; &#8472; ワイエルシュトラスのP
&sim; &#8764; チルダ演算子
&there4; &#8756; 故に
ϖ &piv; &#982; パイ記号
&ang; &#8736;
° &deg; &#176; 度記号
&perp; &#8869; 直交する
&equiv; &#8801; 合同な
¬ &not; &#172; 否定記号
&forall; &#8704; 任意の
&exist; &#8707; 存在する
&and; &#8743; 論理積
&or; &#8744; 論理和
&empty; &#8709; 空集合
&cap; &#8745; 集合積
&cup; &#8746; 集合和
&isin; &#8712; ~の要素である
&notin; &#8713; ~の要素ではない
&ni; &#8715; ~を要素として含む
&sub; &#8834; 含まれる
&sup; &#8835; 含む
&nsub; &#8836; 含まれない
&sube; &#8838; 含まれるか等しい
&supe; &#8839; 含むか等しい
&sdot; &#8901; 点演算子
&lowast; &#8727; アスタリスク演算子
&oplus; &#8853; 丸囲み加算(直和)
&otimes; &#8855; 丸囲み乗算(直積)
&lceil; &#8968; 左上限
&lfloor; &#8970; 左下限
&rceil; &#8969; 右上限
&rfloor; &#8971; 右下限

 

飾り付きアルファベット・合字(リガチャ)
実体参照 コード参照 名称・解説
´ &acute; &#180; アキュートアクセント
¸ &cedil; &#184; セディラ(セディーユ)
ˆ &circ; &#710; サーカムフレックス
¯ &macr; &#175; マクロン
˜ &tilde; &#732; チルダ
¨ &uml; &#168; ウムラウト(ダイエリシス)
á &aacute; &#225; 小文字Aアキュート
Á &Aacute; &#193; 大文字Aアキュート
â &acirc; &#226; 小文字Aサーカムフレックス
 &Acirc; &#194; 大文字Aサーカムフレックス
æ &aelig; &#230; 小文字AE合字(リガチャ)
Æ &AElig; &#198; 大文字AE合字(リガチャ)
à &agrave; &#224; 小文字Aグレーブ
À &Agrave; &#192; 大文字Aグレーブ
å &aring; &#229; 小文字Aリング
Å &Aring; &#197; 大文字Aリング
ã &atilde; &#227; 小文字Aチルダ
à &Atilde; &#195; 大文字Aチルダ
ä &auml; &#228; 小文字Aウムラウト
Ä &Auml; &#196; 大文字Aウムラウト
ç &ccedil; &#231; 小文字Cセディラ
Ç &Ccedil; &#199; 大文字Cセディラ
é &eacute; &#233; 小文字Eアキュート
É &Eacute; &#201; 大文字Eアキュート
ê &ecirc; &#234; 小文字Eサーカムフレックス
Ê &Ecirc; &#202; 大文字Eサーカムフレックス
è &egrave; &#232; 小文字Eグレーブ
È &Egrave; &#200; 大文字Eグレーブ
ð &eth; &#240; 小文字Eth(アイスランド語)
Ð &ETH; &#208; 大文字Eth(アイスランド語)
ë &euml; &#235; 小文字Eウムラウト
Ë &Euml; &#203; 大文字Eウムラウト
í &iacute; &#237; 小文字Iアキュート
Í &Iacute; &#205; 大文字Iアキュート
î &icirc; &#238; 小文字Iサーカムフレックス
Î &Icirc; &#206; 大文字Iサーカムフレックス
ì &igrave; &#236; 小文字Iグレーブ
Ì &Igrave; &#204; 大文字Iグレーブ
ï &iuml; &#239; 小文字Iウムラウト
Ï &Iuml; &#207; 大文字Iウムラウト
ñ &ntilde; &#241; 小文字Nチルダ
Ñ &Ntilde; &#209; 大文字Nチルダ
ó &oacute; &#243; 小文字Oアキュート
Ó &Oacute; &#211; 大文字Oアキュート
ô &ocirc; &#244; 小文字Oサーカムフレックス
Ô &Ocirc; &#212; 大文字Oサーカムフレックス
ò &ograve; &#242; 小文字Oグレーブ
Ò &Ograve; &#210; 大文字Oグレーブ
ø &oslash; &#248; 小文字Oスラッシュ
Ø &Oslash; &#216; 大文字Oスラッシュ
õ &otilde; &#245; 小文字Oチルダ
Õ &Otilde; &#213; 大文字Oチルダ
ö &ouml; &#246; 小文字Oウムラウト
Ö &Ouml; &#214; 大文字Oウムラウト
œ &oelig; &#339; 小文字OE合字(リガチャ)
Œ &OElig; &#338; 大文字OE合字(リガチャ)
ß &szlig; &#223; エスツェット(ドイツ語)
š &scaron; &#353; 小文字Sキャロン(ハーチェク)
Š &Scaron; &#352; 大文字Sキャロン(ハーチェク)
þ &thorn; &#254; 小文字Thorn(アイスランド語)
Þ &THORN; &#222; 大文字Thorn(アイスランド語)
ú &uacute; &#250; 小文字Uアキュート
Ú &Uacute; &#218; 大文字Uアキュート
û &ucirc; &#251; 小文字Uサーカムフレックス
Û &Ucirc; &#219; 大文字Uサーカムフレックス
ù &ugrave; &#249; 小文字Uグレーブ
Ù &Ugrave; &#217; 大文字Uグレーブ
ü &uuml; &#252; 小文字Uウムラウト
Ü &Uuml; &#220; 大文字Uウムラウト
ý &yacute; &#253; 小文字Yアキュート
Ý &Yacute; &#221; 大文字Yアキュート
ÿ &yuml; &#255; 小文字Yウムラウト
Ÿ &Yuml; &#376; 大文字Yウムラウト
ギリシャ文字
Α &Alpha; &#913; 大文字アルファ
α &alpha; &#945; 小文字アルファ
Β &Beta; &#914; 大文字ベータ
β &beta; &#946; 小文字ベータ
Γ &Gamma; &#915; 大文字ガンマ
γ &gamma; &#947; 小文字ガンマ
Δ &Delta; &#916; 大文字デルタ
δ &delta; &#948; 小文字デルタ
Ε &Epsilon; &#917; 大文字イプシロン
ε &epsilon; &#949; 小文字イプシロン
Ζ &Zeta; &#918; 大文字ゼータ
ζ &zeta; &#950; 小文字ゼータ
Η &Eta; &#919; 大文字エータ
η &eta; &#951; 小文字エータ
Θ &Theta; &#920; 大文字シータ
θ &theta; &#952; 小文字シータ
Ι &Iota; &#921; 大文字イオタ
ι &iota; &#953; 小文字イオタ
Κ &Kappa; &#922; 大文字カッパ
κ &kappa; &#954; 小文字カッパ
Λ &Lambda; &#923; 大文字ラムダ
λ &lambda; &#955; 小文字ラムダ
Μ &Mu; &#924; 大文字ミュー
μ &mu; &#956; 小文字ミュー
Ν &Nu; &#925; 大文字ニュー
ν &nu; &#957; 小文字ニュー
Ξ &Xi; &#926; 大文字クサイ
ξ &xi; &#958; 小文字クサイ
Ο &Omicron; &#927; 大文字オミクロン
ο &omicron; &#959; 小文字オミクロン
Π &Pi; &#928; 大文字パイ
π &pi; &#960; 小文字パイ
Ρ &Rho; &#929; 大文字ロー
ρ &rho; &#961; 小文字ロー
Σ &Sigma; &#931; 大文字シグマ
σ &sigma; &#963; 小文字シグマ
Τ &Tau; &#932; 大文字タウ
τ &tau; &#964; 小文字タウ
Υ &Upsilon; &#933; 大文字ウプシロン
υ &upsilon; &#965; 小文字ウプシロン
Φ &Phi; &#934; 大文字ファイ
φ &phi; &#966; 小文字ファイ
Χ &Chi; &#935; 大文字カイ
χ &chi; &#967; 小文字カイ
Ψ &Psi; &#936; 大文字プサイ
ψ &psi; &#968; 小文字プサイ
Ω &Omega; &#937; 大文字オメガ
ω &omega; &#969; 小文字オメガ

 
 
以上
 
 
参考
HTMLの特殊文字 : IT用語辞典

この記事では,Javaのヒープ・メモリ管理の仕組みについてまとめる。参考にした記事を自分なりに解釈しやすいように読み替えながら書いた。
 

前提知識

ヒープ

OSやアプリケーションソフトが使用するメモリ領域の一種。用途に関係なく自由に確保することができる。
OSからはヒープメモリを確保した位置のアドレスが渡され,アプリケーションソフトはこの値を元にして確保したヒープ領域を使用する。ヒープメモリはアプリケーション側での自由度が高い反面,ガベージコレクション機能がないプログラミング言語(の処理系)では,確保したヒープをすべて手作業で解放しなければならないため,誤解放や解放漏れなどのミスが起こりやすい。このヒープの解放漏れが「メモリリーク」である。
 

JVM

JavaはJVM(Java Virtual Machine)と呼ばれる仮想マシン上で動作している。APIやいくつかのツールとセットでJava実行環境 (JRE) としてリリースされている。この環境を移植することで,さまざまな環境でJavaのプログラムを実行することができる。
 

ガベージ・コレクション

Javaでは,ヒープ上のメモリ領域をJavaオブジェクトに割り当てたり,もしくは割り当て済みの領域を解放したりする処理を,プログラムコードに明示的に記述する必要がない。CやC++では,プログラムが使用するメモリ領域の割り当てや,使用済みの領域の解放を,プログラムコードから明示的に指示しなくてはならない。Javaでは,こうしたメモリ管理がJVMによって自動的に行われている。JVMは,Javaプログラムのどこからも参照されなくなった不要なJavaオブジェクトを見つけ出し,そのメモリ領域を自動的に解放する。こうしたJavaオブジェクトの削除処理は「ガベージ・コレクション」と呼ばれる。
 

JVMで使用するメモリ空間の構成

メモリ空間の具体的なイメージを図で表すと以下のようになる。
 
Java メモリ全体構成図
 

Eden領域

new演算子によって作成されたJavaオブジェクトが最初に格納される領域である。
 

Survivor領域

New領域に格納されていたJavaオブジェクトのうち,ガベージ・コレクション実行時に破棄されなかったJavaオブジェクトが格納される領域である。Survivor領域は,From空間とTo空間で構成される。From空間とTo空間のサイズは同じ。
 

Tenured領域

長期間必要であると判断されたJavaオブジェクトが格納される領域である。Survivor領域で指定回数を超えてガベージ・コレクションの実行対象となり,破棄されなかったJavaオブジェクトが,この領域に移動される。
 

Permanent領域

ロードされたclassなどの情報が格納される領域である。
 

Cヒープ領域

JVM自身が使用する領域である。
 

スタック領域

Javaスレッドのスタック領域である。
 

JVM固有空間のヒープ・メモリの構造について

Javaにおけるガベージ・コレクションのメカニズムを理解するには,ヒープ・メモリの構造を知っておく必要がある。JVM固有空間には大きく分けて以下の2つの領域がある。

  • New領域
  • Old領域

New領域には新しいオブジェクトが格納され,Old領域には古いオブジェクトが格納される。生まれてすぐに不要となる短命なオブジェクトはNew領域でその一生を過ごし,長時間存在するオブジェクトはOld領域に留まることになる。
 
以下は,JVMにおけるヒープ・メモリの構造を示したものである。
 
Java JVMのメモリ構成
 
JVMでは,「Scavenge GC」と「Full GC」という2種類のガベージ・コレクションが実行される。Scavenge GCはNew領域のみを対象とした短時間で終了するガベージ・コレクションであり,頻繁に実施される。一方,Full GCはNew領域とOld領域,両方の領域を対象とした大がかりなガベージ・コレクションであり,比較的低い頻度で実施される。こうした理由から,ヒープ・メモリ全体がオブジェクトの世代別に分割されている。
 
JVMのデフォルト設定では,New領域の起動時のサイズが2MB,最大サイズが16MBにセットされている。また,Old領域の起動時のサイズは4MB,最大サイズは48MBである。これらのサイズは,以下のJVMオプションを用いることで変更することができる。
 

オプション名 内容
最初の3種類のオプションについては,指定するサイズをメガバイト単位で指定する。例えば「-Xmn256m」は,New領域に256MBを割り当てることを意味する。
-Xms ヒープ・メモリ全体の起動時のサイズ
-Xmx ヒープ・メモリ全体の最大サイズ
-Xmn NEW領域のサイズ
-XX:SurvivorRatio= Eden領域のサイズをFromまたはTo領域のサイズで割った値(FromとTo領域は同じサイズ)

 

JVMにおけるガベージ・コレクションのメカニズム

New領域はさらに「Eden」「From」「To」という3つの領域に分割されている。これらのうち,Eden領域は,新しいオブジェクトが作成された際に最初に配置されるメモリ領域である。Eden領域は,時間が経つとともに新しいオブジェクトで埋め尽くされていく。Eden領域が満杯になると,前述したScavenge GCが実行される。このとき,まだ使用中のオブジェクト(すなわち,他のオブジェクトから参照されているオブジェクト)についてはEden領域からTo領域へと移動され,参照されていない不要なオブジェクトは破棄される。これにより,Eden領域全体がクリーンアップされ,再び新しいオブジェクトを受け入れ可能となる。
 
Java JVM上でのGC Eden領域からTo空間への移動
 
ここで,To領域に移動されたオブジェクトには「1」という数値が振られる。これはScavenge GCによってオブジェクトが移動した回数を表している。この数値の意味については追って説明する。
 
続いて,Eden領域が再度満杯になり,2回目のScavenge GCが実行される状況を考える。このとき,前回のGC時のFrom領域とTo領域は互いに入れ替わることになる。つまり,前回のGCでオブジェクトの移動先とされたTo領域は,次回のGCではFrom領域として扱われるわけだ。
そして,このFrom領域とEden領域にある使用中のオブジェクトが,再び行われるガベージ・コレクションを生き残ると,To領域に移動される。
このように,Scavenge GCでは,オブジェクトが不要になるまでの間,From領域とTo領域の間でオブジェクトの移動を繰り返す。そして,この移動の際には,オブジェクトに振られた移動回数の数値がカウントアップされる。
Scavenge GCでは,この移動回数が「MaxTenuringThreshold」と呼ばれる閾値を上回るオブジェクトについて,Old領域への移動を行う。
 
Java JVM上でのガベージコレクション
 
JVMにおけるMaxTenuringThresholdのデフォルト値は32に設定されている。よって新しいオブジェクトは,最大で32回までScavenge GCの対象となり,その間をFrom領域とTo領域の中で過ごす。この回数を超えて生き延びたオブジェクトは「寿命の長いオブジェクト(tenured object)」としてOld領域に移動される仕組みになっている。
 

スタック領域について

一番初めに示した図の「スタック領域」について詳しく説明する。スタック領域では,ローカル変数が管理されている。ローカル変数とは,メソッドやメソッド内のfor,if等のスコープで定義される変数のことで,スタック変数とも呼ばれる。
プログラムを実行中にメソッド呼び出しが行なわれると,Permanent領域に格納されているクラス情報からメソッド内容を読み込み,スタック領域に展開して処理を実行していく。スタック領域に積まれる単位は(メソッド,for,if等の)処理スコープ単位である。なお,スコープ内の処理が全て完了すると,スタック領域に積まれた内容は破棄される。メソッド内で宣言した変数やfor文内で宣言した変数が,そのスコープを脱出すると利用できなくなる理由は,このスタック領域の管理仕様によるものだ。
 
Permanent領域とスタック領域の関係
 

「プリミティブ型」と「参照型」はメモリ管理の仕組みが異なる

変数には大きく分けて「プリミティブ型」と「参照型」の2つが存在する。そして,プリミティブ型と参照型ではメモリ管理の仕組みが異なる。
プリミティブ型では,値がスタック領域に直接格納される。対して,参照型ではスタック領域にヒープの参照情報(アドレス)が格納される。
 
参照型変数の挙動
 
参照型の変数は,Permanent領域に格納された情報からヒープ領域へインスタンスの展開を行い,参照情報(アドレス)を元にヒープ領域に展開されたインスタンスへアクセスする。
 
 
以上
 
 
参考
ヒープとは – 意味/解説/説明/定義 : IT用語辞典
JVMとGCのしくみ – ITエンジニアとして生きる
第7回 HotSpot JVMではどのようにオブジェクトが移動するのか:Javaはどのように動くのか~図解でわかるJVMの仕組み|gihyo.jp … 技術評論社
Java:意外と教わる機会の少ないメモリ管理のお話(4) – omotenashi-mind
技術の広場 – Javaの知られざる欠陥(上):ITpro
JavaVMで使用するメモリ空間の構成とJavaVMオプション
チューニングのためのJava VM講座(前編):Hotspot VMの基本構造を理解する (1/2) – @IT
Javaパフォーマンスチューニング(6):HotSpot VMの特性を知る (1/2) – @IT
JVMのメモリ管理 – やさしいデスマーチ