JEP 277: Enhanced Deprecation
Owner | Stuart Marks |
Created | 2014/11/20 23:58 |
Updated | 2015/10/28 20:22 |
Type | Feature |
Status | Candidate |
Component | core-libs |
Scope | SE |
Discussion | jdk9 dash dev at openjdk dot java dot net |
Effort | M |
Duration | M |
Priority | 2 |
Reviewed by | Mark Reinhold |
Release | 9 |
Issue | 8065614 |
Translated by | Shinya Yoshida |
要約(Summary)
非推奨アノテーション(@Deprecated)を改定し,機能のライフサイクルの最後をより確かなものにします.
ゴール(Goals)
仕様中で,APIの状態や意図した処分に関するより良い情報を提供します.
アプリケーションの非推奨APIの動的な使用のログを取るための警告を吐くようにランタイムを増強します.
アプリケーションの非推奨APIの使用に関する静的な情報を生成するツールを提供します.
機能のライフサイクルに関するJava SEとJDKのポリシーを明確化します. 特に,機能を非推奨と注釈することに関する要求と機能が削除される前に与えられるべき告知の量についてです. 結果として適切なタイミングで過去の機能を削除出来るようになるはずです.
Reason
という列挙型.この型の定数と定義は後述されます.value()
メソッドはReason[]
を返します.デフォルト値は列挙型の要素のUNSPECIFIEDです. この値は列挙型の一つ以上の定数の組み合わせになりますが,すべての値の組み合わせは意味をなしません. 空の配列を指定する事は構文的には可能です. この場合はUNSPECIFIEDが与えられたものとして扱うべきです.replacement()
メソッドはString[]
を返します. このメソッドで返される文字列は非推奨APIを置き換えるAPIへのリンクです. それぞれの文字列はJavadocタグの@link
と同じフォーマットであるべきです.since()
メソッドはString
を返します. この文字列はAPIが非推奨になった時のリリースナンバーです. 構文は自由ですが,リリースナンバリングはJavadocタグの@since
のスキームと同じにするべきです. この値がJavadocの@since
タグと冗長ではないことに注意してください. なぜなら,@since
タグはそのAPIが導入されたリリースが記録されているのに対し,@Deprecated
アノテーションのsince()
メソッドが返す値はそのAPIが非推奨になったリリースを記録しているからです.UNSPECIFIED. このAPIは他の理由で非推奨になりました. これはデフォルト値です. 今日,暗に非推奨とされているすべてのAPIの非推奨理由はUNSPECIFIEDです.
CONDEMNED. このAPIは将来のJDKリリースで削除される予定です. Note, the use of the word "condemned" here is used in the sense of a structure that is intended to be torn down. The term is not mean to imply any moral censure.
DANGEROUS. このAPIを使用すると,データロスやデッドロック,セキュリティ上の脆弱性,不正確な結果,JVMの正確性の欠如といった結果を招く可能性があります.
OBSOLETE. このAPIはもはや必要ではなく,このAPIの使用は削除されるべきです. 置き換え可能なAPIは存在しません. OBSOLETEなAPIはCONDEMNEDとしてマークされるかもしれませんし,されないかもしれません.
SUPERSEDED. このAPIは新しいAPIで置き換えられており,このAPIの使用はこのAPIから新しいAPIに変更されるべきです. OBSOLETEなAPIはCONDEMNEDとしてマークされるかもしれませんし,されないかもしれません.
UNIMPLEMENTED. このAPIの呼び出しは意味がないか常に例外が投げられます.
EXPERIMENTAL. このAPIは仕様で策定されておらず,いつか互換性の無い形で変更されるか,削除されるかもしれません.
@Deprecated(SUPERSEDED)をHashtableとStack,Dictionary,Vector,Timerに追加します.
@Deprecated(OBSOLETE)をProcessクラスの引数を取らないコンストラクタに追加します.
Thread.destroy()とThread.stop(Throwable)が@Deprecated({UNIMPLEMENTED, CONDEMNED})として注釈されるように修正します.
Thread.suspend()とThread.resume(),オーバーロードされた引数を取らないThread.stop()が@Deprecated(DANGEROUS)として注釈されるように修正します.
java.awt.Component.show()とhide()から@Deprecatedを削除します.
javacにオプションが与えられない限り,非推奨APIがコンパイル時に不可視にする. これは-Xlint:deprecation -Werrorと比べて有用かはわかりません.
Revisit the version-specific compiler option idea from the requirements document. Note, this would need to have some kind of version information in the annotation itself.
削除のためのもっと厳格なプロセスの定義.どんな通告が必要か?明確な期限があるか?もしくは,メジャリリースのタイミングか?アップデートによって削除できるか?
Despite this being listed as non-goal, reconcile the annotation with Javadoc tag, or at least have some explanation of this issue.
CONDEMNEDは実際のところ理由ではなく性質です.別の値空間になるべきか?
文字列の値(説明?)を@Deprecationアノテーションに追加.Javadocの@deprecatedタグへの記述を置き換えるか?
What to do about deprecated features that don't have APIs to which an annotation or Javadoc can be attached? Various such non-API features have been declared to be deprecated in the past; for example, apt (which has since been removed), RMI static stubs, RMI HTTP and CGI proxying, and secure hashing and encryption algorithms. There may need to be a catalog of these or some other means of tracking them.
Should EXPERIMENTAL differentiate between APIs that can change incompatibly only at major releases vs at any time?
EXPERIMENTAL is a bit of an outlier since it doesn't seem relevant to the tail end of the API life cycle. That is, it applies mainly to new APIs, not old ones. However, an experimental API might be introduced at some point, and quickly withdrawn in favor of the real one (or nothing at all). Changing an API is mostly equivalent to removing the old one and introducing the new one. Thus, experimental APIs are those that have a potentially short life cycle, so even at the time they're introduced, it is likely that they'll be removed soon.
OBSOLETEとSUPERSEDEDの両方が必要かどうかは不明.
Need to consider how to deprecate features controlled by properties. For example, how to deprecate
java.util.Arrays.useLegacyMergeSort
? Perhaps have the library check for the runtime deprecation warning flag having been set.メソッドとコンストラクタを非推奨にするためには,恐らく,1)クライエントからの呼び出し,2)サブクラスからの呼び出し,3)サブクラスからのオーバライドを区別しなければいけない.
状態を確認できる外部の資料へのリンクを(Javadocか)どこかで提供しなければいけないかもしれない.バグリポートか?
See also http://mreinhold.org/blog/removing-features and JSR 270. Note, actual JSR 270 policy states that features aren't actually deleted but instead are made optional (but they might not be present in every implementation). TCK still has them but of course enabled optionally. Also mentions of co-bundled jars and endorsed standards mechanism. Need to reconcile that with current modularity work.
JLS 9.6.4.6への影響.
ゴールでないもの(Non-Goals)
Javadocの@deprecated
タグとjava.lang.Deprecated
アノテーションを統一することは,このプロジェクトのゴールではありません.
動機(Motivation)
Java SEの非推奨の仕組みは改定される必要があります. 非推奨の仕組みは矛盾した状態であり,その意味や適切な使用についての混乱があります.
非推奨の仕組みはJDK 1.1でJavadocのタグとして導入されました.
@Deprecated
アノテーションはJava SE 5で導入されました.
@Deprecated
アノテーションのAPI仕様は,
注釈@Deprecatedの付いたプログラム要素は、一般に危険であったり,より適切なほかのプログラム要素で代用できることもあり,プログラマには使用を薦められないプログラム要素です.推奨されていないプログラム要素が使用されている場合,あるいは推奨されているコードにおいてオーバーライドされている場合,コンパイラが警告を発します.
Java言語仕様の§9.6.4.6はまったく同じです. 最初の文章は上で引用されたAPI仕様の最初の文章と同じです JLSでは,コンパイラが警告を発さなければいけない状況についてより詳細に記述されています.
これらの仕組みは,アプリケーションが別のものに移行することを推進し,アプリケーションが新たに非推奨APIに依存する事を思い留まるように ,APIがライフサイクルの最後を迎えるという事をブロードキャストすることを意図していました. 仕様の中で明確には述べられていないにも関わらず,様々な文書で,いつか非推奨APIが削除されるだろうと述べられています.
@Deprecated
アノテーションは結果的に複数の異なった目的で使われてしまっています.
何も削除されるべきではないと考える人たちによって,非推奨APIは実際にはほとんど削除されていません.
一方で,非推奨になったら,いつか削除されるだろうと思っている人たちもおり,混乱が生じています.
どちらも意図したものではありませんでした.
このことは開発者に伝わった@Deprecated
の意味と,そしてなにより,開発者が非推奨APIの使用に出会った時に何をするべきかが不明瞭だったために起きました.
非推奨が実際のところ何を意味するのかということで皆が混乱しており,更には誰も非推奨を深刻に捉えていません.
このことはJava SEから何かを削除することをどんどん困難にしています.
非推奨についての別の問題は,警告がコンパイル時にしか起こらないことです. APIが将来のJDKで非推奨になっても,既存のバイナリは警告無しにその非推奨APIに依存し,使用を続けてしまいます. APIが非推奨になって何回かJDKリリースがあったとしても,非推奨APIが削除されたら,古いアプリケーションバイナリを使用しているユーザに不快な驚きを与えてしまうでしょう. 警告が出ることもなく,アプリケーションが突然リンクエラーで起動できなくなってしまうでしょう. 更に酷いことに,既存のバイナリが非推奨なAPIに依存しているかどうかを開発者が確認する方法がありません. This causes significant tension between binary compatibility and the need to evolve the specification through the retirement of old APIs.
概要(Description)
仕様(Specification):定義(Definitions)
@Deprecated
アノテーションの増強の主要な目的はAPIの非推奨の状態についてのきめ細かい情報をツールとランタイムに提供することです.
したがって,その情報は最小かつ十分に定められている必要があります.
以下のメンバーがjava.lang.Deprecated
アノテーションに追加されます.
仕様(Specification):列挙型の定数(Enumeration constants)
仕様(Specification):アノテーションの使用のアップデート(Updating annotation usage)
JDK内での@Deprecated
の既存の使用を調べます.そして,ふさわしいように,Reason
の値について更新するか,そのアノテーションを削除します.
実装(Implementation):ランタイムの変更(Runtime changes)
JREはオプトインの原則に基づいて,非推奨APIの使用についての警告を発する方法を提供するべきです. 例えば,非推奨クラスが読み込まれた際に警告を発するための"-verbose:deprecation"といったコマンドラインオプションが追加されるかもしれません. 非推奨のメソッドが呼ばれた時に警告が発せられるといった,きめ細かい設定も考慮されるべきです. もしも非推奨でAPIでない機能が使われた時に警告文を発するために,非推奨の警告の設定も実行時にライブラリのコードからアクセス出来るようになるべきです.
警告文は警告の原因をはっきりと指し示し,"grep"での検索に適したキーワードを含んでなければいけません. 「非推奨」("deprecated")の様な単語が該当します. 特定のファイルに非推奨の警告を出す手段を提供することは,(JVMがこれを認めるなら,)検討に値します.
理由によって発せられる警告を選択できるようなラインタイムオプションを提供します.
もしも実行時の警告のためのオプションが提供されなければ,非推奨のAPIや機能の使用は暗黙的に認められ,性能への明らかな影響は無いです.
実装(Implementation):依存解析ツール(Dependency-tool enhancements)
開発者がJARファイル(やクラスファイルの他のコンテナ)内で非推奨なクラスやメンバーの使用があるかを調査できる静的解析ツールを提供します.
これはjdeps
の機能に似ており,実際として,jdeps
の拡張か修正として提供されるでしょう.
実装(Implementation):Javadocの増強(Javadoc enhancements)
@Deprecated
の理由を扱えるようにjavadoc
を増強します.
また,Reason
の値についてのより一層目立つ表示も行うべきでしょう.
The javadoc
tool should be enhanced to handle the reason code of a @Deprecated
annotation.
It should also provide a more prominent display of the Reason
values.
The handling @deprecated
Javadoc tag should be largely unchanged, though perhaps it might be modified somewhat to include information about the Reason
values.
標準docletが非推奨APIを著しく違うように扱えるように修正するかもしれません. 例えば,クラス内の非推奨のメンバは,インスタンスメソッドや抽象メソッド,具象メソッドについての既存のタブの隣の別のタブに入れられるかもしれません. 非推奨のクラスはパッケージフレーム内の別のセクションに移動されるでしょう. 現在は,インタフェースとクラス,列挙型,例外,エラー,アノテーションについてのセクションがあります. これに,非推奨メンバーについてのセクションが追加されるでしょう.
また,非推奨APIの一覧も増強されるでしょう(この一覧へは各ページの一番上にあるOverview,Package,Class,Use,Tree,Deprecated,Index,Helpというリンクがあるバーから飛ぶことが出来ます). この一覧はインタフェース,クラス,例外,アノテーション,フィールド,メソッド,コンストラクタ,アノテーションの要素という種類ごとにまとめられています.
実装(Implementation):他のツール(Other tools)
非推奨アノテーションの増強はIDEや静的解析システムといった他のツールに影響を与えます. 他のツールの修正はこのJEPの範囲外ですが, このJEPではどのようにそれらのツールを修正するべきかという勧告を与えます. 例えば,非推奨APIはIDEの自動補完メニューやダイアログにおいて標準で非表示にされるべきです. 他の例としては,自動リファクタリングルールでは非推奨のAPIの呼び出しを置き換え可能なAPIへの呼び出しに変更できます.
代案(Alternatives)
非推奨の機能の使用が検出されたら,JVMを停止させるという代案が考えられます. これをすると非推奨の機能からの移行を強制させるのに役立つ様に思えますが,実際問題として,かなり使いにくい上に,開発者や管理者が必要とする情報を提供できません. 非推奨の機能が使われた時に停止させると,非推奨の機能の使用を一つづつしか伝えられません. すべての非推奨の使用を見つけるためには,通常通りにシステムを動かすことができて,実行が終了した後に解析可能な警告が必要です. アプリケーションの非推奨な機能の使用についてのより完全な情報を提供することができます.
非推奨の機能はデフォルトでは利用不可とし,バージョンを明示したフラグが与えられた時だけ利用可能とする事も代案です. これはうまく行きそうですが,残念ながら予期した効果はないでしょう. 管理者は,JDKの新しいバージョンに移行する際には単に"-XenableJava10DeprecatedFeatures"といったフラグを与えれば良いと思ってしまいます. これだと,どの非推奨APIが実際に使われていて,修正に取り組まなければいけないかという情報が提供されません.
@Deprecated
アノテーションを残して,Javadocの@deprecated
タグを無くすことも提案されました.
@deprecated
タグと@Deprecated
アノテーションは常に両方が与えられるかそうでないかで,一方だけで用いると意味を成さないため,一見すると冗長です.
しかし,それぞれ異なる対象に異なる情報をもたらします.
Javadocの@deprecated
タグはドキュメントに含める文章を提供します.
@Deprecated
アノテーションはツールやランタイムに対してきめ細かい情報を与えます.
ドキュメントのための文章をアノテーションの値に統合すると,ドキュメントのための文章でランタイムイメージを汚してしまいます.
また,Javadocが現在のドキュメントにあるコメントの代わりにアノテーションから文字列を抜き出せるようにするという追加の仕事が必要です.
テスト(Testing)
TBD
リスクと仮説(Risks and Assumptions)
TBD
依存性(Dependences)
TBD