連載:明解.NETテクノロジ

アプリケーション・ドメイン
Application Domain

吉松 史彰
2003/10/22
Page1 Page2

概要

 アプリケーション・ドメインとは、共通言語ランタイム(CLR)における、実行コードの管理単位である。従来のWindowsにおけるプロセスに相当する。アプリケーション・ドメインの機能は、AppDomainクラス(System名前空間)を介して外部に公開されている。

従来のプロセスの成り立ち

 Windows上でアプリケーションが実行されると、対応する「プロセス」が作成される。Windowsのプロセスは、メモリ領域、セキュリティ・トークン、ファイルやシリアル・ポートなどの各種リソースなどの管理単位となる。Windowsのプロセスの内部には1つ以上のスレッドが配置され、コードが実行される。同じプロセス内部のスレッドで動作しているコードは、メモリ空間やファイルなどのリソースを共有することになる。

 Windows 3.1では、メモリ領域はWindows全体で管理されており、あるアプリケーションが設定したメモリ上の値を、ほかのアプリケーションが参照できるようになっていた。そのため、アプリケーションが誤動作を起こすと、そのアプリケーションだけではなくほかのアプリケーションまで巻き込んでしまったり、最悪の場合はWindowsシステムまでもが巻き込まれてダウンしてしまったりすることがしばしばあった。

Windows 3.1におけるメモリ領域の管理
メモリ領域はWindows全体で管理されていたため、アプリケーションの誤動作がほかのアプリケーションや、最悪の場合Windowsシステムまでも巻き込んでしまうことがしばしばあった。

 Windows NT以降では、堅牢性を高めるために、アプリケーションが個別のプロセスとして起動されるようになった。各アプリケーションにはそれぞれ専用のメモリ空間が割り当てられ、ほかのアプリケーションのメモリにアクセスしたり、OSのメモリにアクセスしたりすることはできなくなった。

Windows NTにおけるメモリ領域の管理
アプリケーションは個別のプロセスとして起動され、それぞれ専用のメモリ空間が割り当てられる。ほかのアプリケーションやWindowsシステム自体のメモリ領域にはアクセスできない。

 これによって堅牢性は向上したが、OSは大きな負荷を背負い込むことになった。一般に、1つのOS上で動作しているプロセスの数が増えれば増えるほど、OS自体の管理作業が増大し、動作が重くなってしまう。プロセスを分けることで堅牢性は高まったが、パフォーマンスが犠牲になってしまったのである。

共通言語ランタイムにおける型の安全性

 共通言語ランタイム(CLR)では、堅牢性をよりいっそう高めるために、型の安全性(タイプ・セーフティ)という概念を導入している。この概念は、次のようなC++のコードで説明できる。

#include <iostream>
using namespace std;

class Data {
public:
  short x;
  short y;
};

class Data2 {
public:
  long z;
};

void main() {
  Data *d = new Data();
  d->x = 100;
  d->y = 200;
  cout << d->x << ", " << d->y << endl; // 出力
:100, 200

  Data2 *d2 = (Data2*)d;  // <-問題のコード
  if (d2)
    d2->z = 9876543;
  cout << d->x << ", " << d->y << endl; // 出力:-19393, 150

  delete d;
  d = NULL;
}
// コンパイル方法:cl /GX badcode.cpp
型の安全性を示すためのサンプル・プログラム(アンマネージ・コード)
C++で記述されたこのコードからは、従来形式のネイティブ・コード(アンマネージ・コード)ができあがる。この形式では、互換性がない型へ強制的にキャストを行っていてもプログラムは実行できる。なお、.NET Framework SDKがインストールされていればこのコードはコンパイル可能。

 上記のコードは、コンパイルでき実行も可能であるが、結果としてDataクラスのインスタンスのデータを破壊する。「問題のコード」部分で、本来互換性のないキャストが行われてしまうためである。

互換性のないキャストにより破壊されるデータ
従来のアンマネージ・コードでは、2つのshort型(16ビット)の値をlong型(32ビット)としてアクセスするといったコードが記述できてしまう。この場合、もともと代入されていた2つの値は破壊され、意味のない値となってしまう。

 上記のコードを共通言語ランタイム上で動作するように次のように書き換えてみよう。次のコードは(warningが出力されるものの)コンパイルは可能だ。しかし実行すると、問題のコード部分でSystem.InvalidCastException例外が発生する。

#include <iostream>
using namespace std;

// 追加

#using <mscorlib.dll>

// __gc を追加
__gc class Data {
public:
  short x;
  short y;
};

// __gc を追加
__gc class Data2 {
public:
  long z;
};

void main() {
  // __gc を追加
  Data __gc *d = new Data();
  d->x = 100;
  d->y = 200;
  cout << d->x << ", " << d->y << endl;

  // __gc を追加
  Data2 __gc *d2 = (Data2*)d;  // <-問題のコード
  if (d2)
    d2->z = 9876543;
  cout << d->x << ", " << d->y << endl;
}

// コンパイル方法:cl /clr /GX managedbadcode.cpp
型の安全性を示すためのサンプル・プログラム(マネージ・コード)
オプション“/clr”を付けてコンパイルすると共通言語ランタイムで動作可能なマネージ・コードとしてコンパイルできる。共通言語ランタイム上では互換性のない型同士を強制的に変換するようなコードを実行することはできない。

 従来のC++で記述されたコード(アンマネージ・コード)では、Windowsは「d」が「d2」に代入されてしまうのを拒否できない。Windowsにとってポインタとは決められたサイズの数値であるだけで、それが実際に何を指しているのかを検出して実行を拒否することは不可能だからだ。しかし、共通言語ランタイムという、Windowsに代わる新しい実行環境では、すべてのメモリには対応する「型」が割り当てられており、互換性のない型同士を強制的に変換することはできない。これにより、メモリが破壊されるようなコードを実行することはできなくなった。

 

 INDEX
  明解.NETテクノロジ
  アプリケーション・ドメイン Application Domain
  1.従来のプロセスの成り立ち
    2.共通言語ランタイム版プロセス - アプリケーション・ドメイン
 

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • Kinectが切り開く“夢の近未来” (2012/2/2)
     日本を含めた世界中でKinect for Windowsセンサー商用版とSDK正式版がリリース。未来のコンピューティングはどう変化するのか?
  • 3つの視点でネイティブと.NETの適材適所を考察 (2012/1/31)
     アプリ開発は「ネイティブ」と「.NET」、どちらが最良? その問いには「適材適所」と答えるしかない。では、“適所”は一体どこかを考察する
  • SQL Azure Data Sync入門 (2012/1/30)
     SQL Azure/SQL Serverデータベース間のデータ同期を簡単に実現するサービスとは? その仕組みや使用手順を解説
  • Windows Phoneアプリ市場の現状を分析する (2012/1/27)
     Windows Phone のアプリ・ストアに日々登録されている多種多様なアプリ。カテゴリ別のアプリ数は? 市場の現状を明らかにする

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

- PR -
@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH