目次 | 前の項目


JavaTM 製品のバージョン管理の仕様

1998 年 11 月 30 日


オープンな分散システムは、パッケージ間の多くの依存関係に基づいて的確に運用する必要があります。そのため、更新を注意深く管理する必要があります。 分散システム内の変更は、ユーザ、サポート組織、Web 管理者、および開発者を含む個々のグループに重大な影響を及ぼします。 分散システム内のパッケージの操作は、システム全体の状態に関する部分的な知識だけで正確に行う必要があります。 システムの各パッケージが更新される速度がそれぞれ異なるため、管理はそれだけ難しくなります。 オブジェクト指向の設計手法で個々のパッケージの更新を管理して、パッケージ間の依存関係を明示的に管理することにより、システムの更新が可能になります。 Java 言語は、一貫した更新単位に適したパッケージ、public インタフェースだけを公開し、かつほかのクラスの public インタフェースだけを使用するパッケージを定義します。

はじめに

どのようなシステムでも、時とともに更新していくシステムにはサポートを提供する必要があります。 通常、既存のシステムには、変更の適用方法を指定する規約および機構が定められています。 これらのシステムは、ソフトウェアプログラムがコンピュータにインストールされていることを前提としています。 一般に、開発者は、必要とするほかのパッケージのバージョンを指定し、インストールプロセスは、システムの検証と設定を行います。

しかし、オープンな分散システムでは、既存システムが静的であるという仮定は当てはまりません。 パッケージが変化する方法と時期を制御することは不可能なため、その更新はさらに困難です。 正確な操作は、パッケージ間の莫大な依存関係にかかっています。 オープンで信頼性が高く、かつスケーラブルな分散システムの構築という目標を達成するには、システムパッケージの更新方法を規定する最新の規約と機構のセットが必要です。

このドキュメントでは、次の点を説明します。

要件

分散システム内の変更は、次のグループに重大な影響を与えます。

グループごとに、更新を続けるネットワーク製品に対する異なる要件を満たさなければなりません。

エンドユーザ

エンドユーザには、時の経過とともに Java ベース製品は信頼性および互換性が向上していくという確信を与える必要があります。 ユーザがアップグレードを躊躇する場合、「Write Once, Run Anywhere」という哲学に対するユーザの確信を築くことが必要です。 Java では、「アップグレードしたらどこかに障害が生じる」とか「ほかのユーザが使用するデータを読み書きすることができなくなってしまう」という心配がないようにしなければなりません。

製品サポート組織

製品サポート組織にとって、使用されている製品とその使用環境、および製品パッケージの完成度を正確にかつ容易に識別できることは非常に重要です。

Web マスターおよび管理者

Web マスター、管理者、およびサービスプロバイダは、Web またはネットワークファイルシステムを介してクライアントにアプリケーションを配備するための、信頼性が高く、サポート可能な方法を求めています。

製品開発者

製品開発者は、ユーザ、管理者、およびサポートスタッフの要求を満たすアプリケーションおよびライブラリの記述および配置方法を理解する必要があります。 開発者には、以下の要件を満たす製品およびパッケージの開発が求められます。

分散システムの更新で生じる問題

オープンな分散システムでは、パッケージが拡大し、頻繁に更新される場合に、問題が発生することがあります。 public インタフェースを使用する際に、インタフェース固有の特定動作が維持されないと、予期しない方法でシステムに障害が発生する場合があります。 オープンシステムは、異なる会社や組織が作成したパッケージで構成されています。 これらの組織は、相互に連絡を取りながら運営されているわけではなく、独自のスケジュールで新製品を発表したり、アップグレードしたりします。 アップグレードされた製品の配布には時間がかかり、しかもアップグレードを採用するかどうかという問題もあります。

Java では、ローカルおよび分散システムのコンポーネントは、public インタフェースおよびほかのパッケージの動作規定に依存しています。 それぞれのパッケージは時とともに更新されます。 ほかのパッケージが依存するパッケージは、アップグレード後も期待される動作を継続して提供できなければなりません。

分散システムでは、システム全体の状態を把握することはできないため、部分的に整合性を保つことしかできません。 システムの各プロセスおよび各パッケージは、システムの現在の状態を部分的にしか見ておらず、分散システムのほかの部分に情報を要求することにより情報を蓄積していきます。 情報の断片は、それが起動したアプレット、ロードされたクラス、呼び出されたリモートメソッド、または取得された Web ページのどれからであっても、すでに得ているシステムの情報と一貫性を保って使用できるように、注意深く扱う必要があります。

ロードされたクラス内の不一致により、次のようなエラーが発生する可能性があります。 クラスの検証ができない、行われた不正なクラス計算を認識できない、ユーザが要求した機能が特定不能な障害を示すなどです。

これらの問題は、一般的に次の状況で発生することがあります。

これらの問題は、動的にロードされたパッケージ間の非整合性から発生するため、予防したり、直接解決することはできません。これらのパッケージは 1 人のシステム管理者の管理下にあるわけではないため、現在の設定管理技術では特定することができません。

更新を考慮した設計

これらの問題に対処し、前述の要件を満たす鍵となるのは、パッケージおよびシステムのパッケージ化を注意深く設計し、一貫した単位ごとの更新、配布、およびロードを可能にすることです。 大量生産される製品で一般的なのは、現場での交換が可能な単位という概念です。 これは製品の最小単位で、仕様およびサプライヤによって識別されます。また配布、再配布、および障害がある場合には交換も可能です。 同様のモデルは、ソフトウェアの配布に利用されています。製品には名前やバージョン番号があり、1 つまたは複数の仕様に準拠し、ネットワークまたは CD-ROM によって配布されます。また問題点もサポート組織に報告することができます。 これらのパッケージは、配布、使用、検査、置換、また必要な場合にはアップグレードが可能な最小単位です。 パッケージはほかのパッケージと組み合わせることができますが、そのあともパッケージごとに識別、検証、および配布が可能です。

Java 言語ベースのパッケージ機構は、置き換え可能な単位という考え方とよく適合します。 Java パッケージは、public インタフェースだけを公開し、ほかのパッケージの public インタフェースだけを使用します。 JavaTM 言語仕様は、互換性を維持しつつ更新されるパッケージへのアプローチを定義しています。

下位互換に関する Java 言語仕様

Java 言語仕様は、適正な更新が期待されるパッケージ開発の基礎となります。 以前にコンパイルおよび配布したクラスと下位互換を保ちながら、クラスがどのように変化できるのかを定義するからです。 健全な更新にとって重要なのは、public、protected、および package インタフェースの安定性と、実装更新時の動作です。 Java 言語仕様では、「互換性」のある変化を「既存のインタフェースまたは動作を変更しない変化」と定義しています。 それで、あるクラスがメソッドを定義し、そのメソッドが特定の動作をする場合、同じ規約がクラスのそのあとのバージョンすべてでサポートされなければなりません。 詳細については、「JavaTM Language Specification」の第 13 章を参照してください。 ここでは、互換性のない変更が 1 つ追加されています。 public インタフェースへのメソッドの追加は、互換性がありません。

互換性のない変更は許可されませんが、新規または類似の機能はいつでも、新規または既存のインタフェースやクラスに追加できます。

Java パッケージを更新単位として選択することにより、パッケージおよびクラスのプライベートメソッドで変更できます。これにより、public および protected クラスとメソッドに外部インタフェースおよびセマンティクスを保ちつつ、パッケージの実装に柔軟性を持たせることができます。

下位互換におけるオブジェクトの直列化仕様

コンポーネント間の記憶領域保持機能および通信機能が強力であることは、分散システムにとって重要です。 クラスを拡張しつつ記憶領域中の以前のデータをクラスが読めるようにするには、持続的な記憶領域を維持しつつコンポーネントを更新しなければなりません。 分散システムでは、各コンポーネントの更新速度はそれぞれ異なりますが、コンポーネント間の通信の信頼性は維持しなくてはなりません。

オブジェクトを直列化する際、互換性に関する要件に従うことにより、より新しいまたはより古いバージョンのオブジェクトが一般的かつ一貫した方法で通信することが可能になります。 詳細については、「JavaTM オブジェクト直列化仕様」の第 5 章を参照してください。

パッケージバージョンの仕様

確認の必要な作成物のカテゴリがいくつかあり、それには仕様、実装、Java 仮想マシン、および Java Runtime Environment が含まれます。

仕様のバージョン管理

オープンシステムは、仕様には複数の実装が含まれるという考えに基づいています。 仕様は、組織や企業の援助のもとに更新されます。 仕様に互換性のない複数のバージョンが含まれるというのは、望ましいことではありません。 仕様または実装の各バージョンは、単一の次期バージョンにだけ更新しなければなりません。 仕様に下位互換性を要求する考え方では、仕様を以前の仕様のスーパーセットとみなすことができます。 バージョンの配列順序は 1 通りしかないため、特定のバージョン番号は特定の仕様を意味するセマンティクスを備えています。 仕様のバージョン番号には、ピリオドで区切られた数字で構成されるデューイ 10 進数表記法が使用されます。

仕様は、次の項目で識別できます。

仮想マシンのバージョン

Java 仮想マシンの実装は、仕様と実装の両方から識別する必要があります。 これらのプロパティは、java.lang.System.getProperties を使用してすでに利用可能なものに追加する必要があります。

java.vm.specification.version 例 1.3
java.vm.specification.vendor 例 Sun Microsystems Inc.
java.vm.specification.name 例 JavaTM Virtual Machine Specification
java.vm.version 例 Solaris 5.5 Native 1.0 build32
java.vm.vendor 例 Sun Microsystems Inc.
java.vm.name 例 Solaris 5.x JVM

これらのプロパティへは、java.lang.System.getProperty メソッドを使用してアクセスします。その結果、文字列が返されます。

Java Runtime のバージョン ID

JavaTM Runtime の識別に必要な情報は、すでに 「JavaTM Language Specification」の 20.18.7 で指定されたプロパティにより、java.lang.System.getProperties を使用して部分的に取得されています。

java.version 例 Solaris 1.3
java.vendor 例 Sun Microsystems Inc.

現時点では、これらのプロパティは、JavaTM Runtime の実装および利用可能なコアクラスを識別します。 これらのプロパティは、この JDKTM が実装する JavaTM 言語仕様を識別しません。

この実装が準拠する JavaTM Runtime Environment 仕様のバージョンの識別に必要なプロパティは、次のとおりです。

java.specification.version 例 1.1
java.specification.name JavaTM Language Specification
java.specification.vendor 例 Sun Microsystems Inc.

これらのプロパティには、java.lang.System.getProperty メソッドを使用してアクセスできます。結果として、値が文字列で返されます。

パッケージのバージョン管理

各 JavaTM パッケージは、クラスファイルおよびオプションのリソースファイルで構成されます。 パッケージの中身を識別するために必要な情報も、パッケージの中に格納されています。

この仕様は、パッケージが JavaTM Runtime とともに配布される主要パッケージとして開発されたか、標準拡張として開発されたか、アプレットまたはアプリケーションパッケージとして開発されたかに関係なく、すべてのパッケージに適用されます。

仕様のバージョン番号と異なり、実装のバージョン情報は、パッケージに以前のバージョンと下位互換性があることを示すものではありません。 パッケージのバージョン番号は、バグなどの仕様と実装の相違を識別するためのものです。 実装の新バージョンは、望ましくない動作または不正確な動作を取り除くために作成されるもので、下位互換性を意図したものではありません。 パッケージのバージョンを示す文字列は、任意の固有値を持ち得るため、等価かどうかの比較だけが可能です。 詳細については、「実装のバージョン番号を識別用に限定する理由」を参照してください。

次の属性名は、パッケージごとに定義されます。 それぞれの属性の値は、文字列です。

Implementation-Title パッケージのタイトル
Implementation-Version バージョン番号
Implementation-Vendor ベンダー企業または組織
Specification-Title 仕様のタイトル
Specification-Version バージョン番号
Specification-Vendor ベンダー企業または組織

これらの属性は、マニフェストに保存され、次で説明する java.lang.Package API を使用したプログラムにより取得できます。

JAR マニフェストフォーマット

現在のマニフェストフォーマットは拡張され、パッケージのバージョン情報属性の仕様に対応しました。 マニフェストエントリは、JavaTM パッケージごとに作成する必要があります。 エントリ名は、パッケージのクラスおよびリソースファイルを格納するアーカイブ内のディレクトリ名になります。 例を示します。

Manifest-version: 1.0
Name: java/util/
Specification-Title: Java Utility Classes
Specification-Version: 1.3
Specification-Vendor: Sun Microsystems Inc.
Implementation-Title: java.util
Implementation-Version: build57"
Implementation-Vendor: SunMicrosystems. Inc.

マニフェストにこれらの属性を挿入するには、マニフェストファイルのプロトタイプを作成し、jar ツールの -m スイッチを使用して、マニフェストの構築時に属性をマニフェストにマージします。 今後、jar ツールはマニフェスト中でバージョン属性をブラウズおよび設定できるように拡張される予定です。

Java Plug-in 製品が Jar ファイルにアクセスするときに使用するマニフェスト情報については、「Java Plug-in 開発者ガイド」の「Java 拡張機能の配備」を参照してください。

ユーザが実行中のパッケージを識別する方法

ユーザは、バグの発生時に、使用中のパッケージの ID をレポートしなければなりません。 アプリケーション、アプレット、またはブラウザは、ユーザから要求されたときまたはエラーが発生したときに、入手可能な情報をユーザに公開しなければなりません。 利用可能な API により、次の情報がレポート可能です。

実装のバージョン番号を識別用に限定する理由

実装はそれぞれ独自に、バグの修正、パフォーマンスの向上、または仕様の最新リビジョンで規定された新機能の追加を目的として更新されます。 パッケージは、仕様を実装すると同時に、どのバージョンの仕様を実装したかを識別する必要があります。 パッケージ間のやり取りは、public および protected インタフェースおよびクラス経由でだけ行われます。 public API および動作は、時間が経過しても安定している必要があります。そのため、あるパッケージの実装の変更が、別のパッケージの動作に影響を与えないように注意する必要があります。

パッケージのクラスが常に仕様を忠実に実装している場合には、仕様を識別するだけで十分です。 しかし現実にはこのようなことはまれなので、バグに関係している可能性のあるパッケージが報告されるために、パッケージは自らの身分を明らかにする必要があります。

実装のバージョン識別子に何らかの意味を持たせるのには、重要な目的があります。 バグを追跡するのが目的である場合、固有の番号を付ければ十分目的を果たすことができます。 また、クライアントのパッケージがベンダーのパッケージの特定のバージョンに含まれるバグを回避する場合にも、固有の番号を付けると効果的です。該当する番号のバージョンをテストし、バグを回避できるからです。

ただし、1 つのパッケージがほかのパッケージに含まれるバグを回避しようとすると、多くの付加的な問題が発生することがあります。 ほかのパッケージは、仕様の一部ではない動作を識別する必要があり、実装にだけ属する動作を使用しようとするかもしれません。 そのような実装固有の動作は、開発者によって確認およびテストされた特定のバージョンでない限り、信用することはできません。

ベンダーパッケージのあるバージョンで初めて発生したバグは、次のバージョンでも障害になる場合と、ならない場合とがあります。 バグを含むパッケージのクライアントが、バージョン番号に基づくバグの回避を行うと、特定のバージョンのバグを正しく回避できる場合があります。 バグを含むパッケージが修正された場合、クライアントパッケージはバグが修正されたかどうかをどのようにして知ることができるのでしょうか。 あとのバージョンにもバグが含まれていると仮定した場合、クライアントは依然としてバグを回避する処置をとらなければなりません。 バグを含まないパッケージでは、バグの回避そのものが正しく機能しない可能性があります。 このため、バグの修正により一連のバグが発生する可能性があります。 新しいバージョンをテストすることにより、バグの回避が必要か、あるいはバグの回避が正常に動作しているパッケージに問題を発生させることになるのかを見極めることができるのは、開発者だけです。 また、あるバージョンにバグが存在することを知っているのは、開発者だけです。


目次 | 前の項目


Copyright © 1998 Sun Microsystems, Inc. All Rights Reserved.