注: この Java 配備ガイドでは、Java SE 6 update 10 リリースより前にリリースされた機能について説明します。最新情報については、Java Rich Internet Application の開発および配備を参照してください。
ClassFormatError
このエラーは、古い JDK 1.0.2 または 1.1 コンパイラによって生成されたバイトコードが原因で発生します。これまで、該当するコンパイラによって多くのバイトコードが生成されていますが、いずれも Java VM 仕様に準拠していません。最近の J2SE リリースのべリファイアは不正なクラスフォーマットに関して非常に厳しくなっているため、こうした不正なクラスファイルがロードされると、VM によって ClassFormatError
がスローされます。
古いクラスファイルに関する典型的な問題点は次のとおりです (ただしすべてを網羅したものではない)。
この種類の問題は、現在の JDK にある Javac バイトコードコンパイラを使用してクラスを再コンパイルすれば回避することができます。サードパーティーのオブファスケータを使用する場合は、それが正しいクラスファイル形式に準拠したクラスファイルを作成するかどうかを確認してください。
不正なクラスファイルをもついくつかのアプレットを Java SE で実行できるようにするために、Java Plug-in には、不正なクラスファイルを正しいものに変換するバイトコード変換プログラムが含まれています。現時点では、次の ClassFormatError
による不正なクラスファイルだけが変換されます。
しかし、次の ClassFormatError
の問題は、バイトコード変換プログラムでは解決しません。
そのため、上記の問題を含むクラスファイルは、Java SE では実行できません。
sun.audio
によるセキュリティー例外JDK 1.1 のアプレットでは sun.audio
パッケージにアクセスできました。しかし、Java SE ではアプレットのサンドボックスが閉じられたため、sun.audio
パッケージのクラスライブラリにアクセスしようとしたアプレットは SecurityException
になります。
アプレットの互換性を最大限にするため、Java Plug-in ではアプレットサンドボックスが開けられ、アプレットがふたたび sun.audio
パッケージにアクセスできるようになりました。
AppletContext.getAudioClip()
および AppletContext.getImage()
のリソースが検索できないMicrosoft による実装と Sun による実装では、AppletContext.getImage()
および AppletContext.getAudioClip()
のリソースルックアップシーケンスが異なっています。
Microsoft の実装では、リソースは次の順序で検索されます。
archive
または cabbase
パラメータで指定されたアーカイブcodebase
URLSun による実装では、リソースは単に codebase の URL で検索されます。
この結果、Microsoft VM のリソースルックアップシーケンスに依存したアプレットの中には、Java SE ではリソースを正しくロードできないものがあります。
アプレットの互換性を最大限にするため、Java Plug-in ではリソースルックアップシーケンスが次のように変更されました。
archive
パラメータで指定されたアーカイブcodebase
URLClassLoader
共有ポリシーClassLoader
共有ポリシーは、Microsoft による実装と Sun による実装で異なっています。
Microsoft による実装では、次の場合だけ ClassLoader
オブジェクトがアプレット間で共有されます。
codebase
の値が同じであり、archive
の値が同じであり、かつcabbase
の値が同じである。Sun による実装では、codebase
の値が同じである場合だけ ClassLoader
オブジェクトがアプレット間で共有されます。
Microsoft による実装の ClassLoader
共有ポリシーに依存するアプレットの中には、潜在的なクラス定義の競合のために Java SE では正しく実行されないものもあります。
アプレットの互換性を最大限にするため、Java Plug-in では ClassLoader
共有ポリシーが変更されました。次の場合だけ ClassLoader
オブジェクトがアプレット間で共有されるようになりました。
codebase
の値が同じであり、cache_archive
の値が同じであり、java_archive
の値が同じであり、かつarchive
の値が同じである。Java SE の備えている新しいセキュリティーモデルは、JDK 1.1 よりもはるかにすぐれた機能と柔軟性を提供していますが、Microsoft VM セキュリティーモデルは、JDK 1.1 と独自の技術に基づいています。
この問題は解決不能です。そのため、Microsoft のセキュリティーモデルに依存したアプレットは Java SE では正しく実行されません。
Java SE および JDK 1.1 におけるアプレットのパッケージ化は、.jar
ファイルを通じて実行されますが、Microsoft VM では、.jar
ファイルと独自の .cab
(キャビネット) ファイルを通じて実行されます。
この問題は解決不能です。したがって、Microsoft の .cab
ファイル形式にパッケージ化されたアプレットは Java SE にロードされません。
null
と長さゼロの文字列)JDK 1.1 では、クラスライブラリにおける null
と長さがゼロの文字列の取り扱いに関する Java 言語仕様が緩やかでした。API によっては null
を、長さゼロの文字列として扱うものもあれば、null
を null として扱うものもありました。Java SE では Java 言語仕様が厳密になり、正確な動作を指定するようになりました。
この問題は解決不能です。null
を長さゼロの文字列として処理する API に依存しているアプレットは、Java SE では例外となります。
Java SE では、アプレット署名を RSA および .jar
ファイルを通じてサポートしていますが、Microsoft ではアプレット署名を、独自の Authenticode および .cab
ファイルテクノロジを通じてサポートしています。
この問題は解決不能です。Microsoft の Authenticode および .cab
ファイルテクノロジに依存する署名アプレットは、Java SE では正しくロードされません。
過去には、AWT はスレッドに対して安全であると考えるプログラマがいました。そのため、AWT ライブラリを使用して記述された一部のアプレットは複数のスレッドで GUI とやり取していますが、クラスライブラリが同期化の問題を処理するものとみなしていました。しかし、実際は AWT または Swing のいずれもスレッドに対して安全ではありません。そのため、GUI またはプロセスのイベントを更新するすべてのコードは、イベントディスパッチスレッドで発生しなければなりません。これに失敗すると、デッドロックまたは競合状態になる可能性があります。詳細については、「The Swing Tutorial」の「Concurrenecy in Swing」を参照してください。このチュートリアルの例では特に Swing を扱っていますが、同じ規則がすべての Component
に当てはまります。
Microsoft による実装では、HTML ページの JavaScript で公開されるアプレットのメソッドとプロパティーは、アプレットオブジェクトのメソッドやプロパティーとまったく同じものです。Java Plug-in では、アプレットのメソッドとプロパティーは、JavaBeans のイントロスペクションを通じて HTML の JavaScript で公開されます。JavaBeans のイントロスペクションは、アプレットオブジェクトの命名規則によってメソッドとプロパティーの分析を行います。これによる影響として、アプレットのフィールドがそれぞれ異なる方法で処理されます。
この問題は Java Plug-in の今後のリリースで解決される予定です。現在のところ、Java SE ではアプレットオブジェクトのフィールドにアクセスする JavaScript は正しく動作しません。
Microsoft による VM の実装では、J/Direct、AFC、WFC など多くの独自のクラスライブラリが提供されています。その他のクラス、メソッド、および変数については、「How to avoid potential pitfalls of Microsoft's non-standard SDK for Java」を参照してください。
この問題は解決不能です。Microsoft の独自の Java クラスライブラリに依存したアプレットは Java SE では正しく動作しません。
Applet.getParameter()
から返される文字列内の空白文字Microsoft による実装では、文字列が Applet.getParameter()
内でアプレットに返される前に、空白文字が取り除かれます。しかし、Sun による実装では、文字列は HTML パラメータで指定されたとおりに返されます。この結果、JDK 1.1 アプレットの中には Java SE で実行できないものがあります。JDK 1.1 アプレットのロジックでは、空白を想定していないためです。
アプレットの互換性を最大限にするため、Java Plug-in では Applet.getParameter()
の実装が変更され、戻り値から空白文字が取り除かれています。
java.util.Hashtable.hashCode()
における設計変更 JDK 1.1 では Hashtable.hashCode()
はオブジェクト ID に基づいて実装されているので、hashCode()
が呼び出された場合、Hashtable
オブジェクトはそれぞれ一意の値を返します。Java SE では Hashtable.hashCode()
の実装が、Java Collection Framework の一部として値に基づくものに変更されました。Hashtable
オブジェクトは、格納しているオブジェクトに基づいてハッシュコードの値を返します。
この変更によって、JDK 1.1 のアプレットのいくつかは、Hashtable
オブジェクトをそれ自身に追加した場合に中断してしまいます。なぜなら、この変更は Collection Framework の基本設計を乱し、StackOverflowError
が発生するからです。同じ Hashtable
オブジェクトから一定の値を返すために、Hashtable.hashCode()
に依存しているいくつかのアプレットコードで、ロジックが破壊されてしまいます。
アプレットの互換性を最大限にするため、Hashtable.hashCode()
の実装が変更され、こうした特別なケースをチェックしてスタックのオーバーフローを回避するようになりました。
マウスイベントの追跡やその他の理由により、アプレットがそのフレームにアクセスしようとすることがあります。Microsoft による実装と Sun による実装では、フレームとアプレットの間でコンテナ数が異なります。
Microsoft VM における特定の包含レベルにあるフレームに依存する (AWT 階層コンポーネントツリー全体をナビゲートしない) アプレットは、Java SE では失敗する可能性があります。もっともよく見られる症状は、AWT ディスパッチイベントスレッドからの ClassCastException
です。
この問題は解決不能です。そのため、Java SE ではこの問題を抱えたアプレットは正しく動作しません。
MAYSCRIPT
Netscape Navigator と Java Plug-in では、JavaScript にアクセスするアプレットはアプレット要素で MAYSCRIPT
属性を指定する必要があります。しかし Microsoft による実装ではこの特別なパラメータが重視されないため、アプレットはあらゆる条件下で JavaScript にアクセスすることができます。インターネット上のアプレットのほとんどは、Netscape ではなく Microsoft VM をターゲットにしているため、MAYSCRIPT
が指定されていません。
アプレットの互換性を最大限にするため、Java Plug-in から MAYSCRIPT
のチェックが削除されました。
User-Agent
Microsoft と Sun による実装では、HTTP 接続が要求されたときに、異なる HTTP の User-Agent
の文字列がサーバーに渡されます。多くの Web サイトが Sun ではなく Microsoft VM をターゲットにしているため、こうした Web サイトでは Sun の HTTP の User-Agent.
を認識せず、失敗が起こります。
このため、Java Plug-in で使用されている HTTP の User-Agent
文字列は、Microsoft の User-Agent に似たものにしてきました。こうすることで、ほとんどの Web サーバーでは、Java Plug-in を実行するアプレットからの要求を認識します。
Microsoft と Sun による実装では、アプレットの起動時と停止時に発生するイベントは完全に同じではありません。たとえば、アプレットのロジックが Applet.start()
または Applet.stop()
の呼び出し時に表示されるアプレットに依存することは、Microsoft による実装には当てはまりますが、Sun による実装には当てはまりません。
Microsoft VM においてアプレットが起動および停止するときの特定のイベントに依存しているアプレットは、Java SE では正しく機能しません。もっともよく見られる症状は、AWT ディスパッチイベントスレッドからの NullPointerException
です。
この問題は解決不能です。
Java SE の Java クラスライブラリでは多くの変更が行われました。API の中には明確になったもの、切り下げられたもの、別の実装により置き換えられたものがあります。次に、Microsoft の VM で実行されるアプレットが Java SE では失敗する原因となっているものについて示します。
java.awt.Graphics.drawString()
drawString()
は null
を空の文字列として扱います。Java SE では、drawString()
は null
を null として扱うため、NullPointerException
がスローされます。java.awt.Graphics.drawImage()
drawImage()
は null
イメージを無視します。Java SE では、drawImage()
は null
を null として扱うため、NullPointerException
がスローされます。java.awt.Color
コンストラクタColor
コンストラクタに境界値を上回ったり下回ったりする値が渡された場合、コンソールで警告メッセージが出力されますが、値は最大値または最小値に自動的にリセットされます。Java SE では Color
コンストラクタが不正な値をチェックし、IllegalArgumentException
をスローします。Thread.stop(), Thread.suspend(), Thread.resume()
AccessControlException
が発生します。 これらの問題の影響下にあるアプレットは例外となり、Java SE では正しく実行されません。
これは、Java SE ではサポートされていない、Microsoft 独自のテクノロジです。
object
属性と PARAM
要素従来のアプレット形式では、PARAM
要素と object
属性を同時に使用すると、Sun VM の場合は例外「Either "code" or "object" should be specified, but not both.」がスローされます。Microsoft VM では、例外はスローされません。これは互換性の問題です。Sun VM でこの例外を回避するには、アプレットで object
という名前の属性を PARAM
要素に使用しないでください。