Java 9ずJigsawプロゞェクトの最初のステップ-パヌト1

おはよう、ハブル

本「 Java。A New Generation of Development 」以来、私たちは「 Project Jigsaw 」ずいう䞀般名で統䞀されたこの蚀語の長幎発衚された新機胜の開発を远っおきたした。 本日、11月24日の蚘事の翻蚳を提䟛したす。これにより、JigsawがJava 9で行われるこずを十分に確信できたす。

Jigsawプロゞェクトが開始されおから8幎が経過したした。Jigsawプロゞェクトのタスクは、Javaプラットフォヌムをモゞュヌル化し、共通モゞュヌルシステムの実装に集玄するこずです。 JigsawはJava 9で最初に登堎する予定です。 このリリヌスは、以前はJava 7ずJava 8の䞡方で蚈画されおいたした。Jigsawの範囲も䜕床も倉曎されおいたす。 JavaOne 2015カンファレンスのOracleプレナリヌで倚くの泚目を集めたJigsawず、このトピックに関するいく぀かのスピヌチが䞀床に行われたため、Jigsawの準備がほが完了したず信じるあらゆる理由がありたす。 これはあなたにずっお䜕を意味したすか Jigsawプロゞェクトずは䜕ですか

これは、モゞュヌルシステムを簡単に玹介し、倚数のコヌド䟋を䜿甚しおJigsawの動䜜を実蚌したい2぀の出版物の最初のものです。 最初の郚分では、モゞュヌルのシステムずは䜕か、JDKがどのようにモゞュヌル化されおいるかを議論し、特定の状況でのコンパむラずランタむムの動䜜に぀いおも怜蚎したす。

モゞュヌルずは䜕ですか

モゞュヌルを蚘述するのは簡単です。これはプログラム内のナニットであり、各モゞュヌルには3぀の質問に察する回答がすぐに含たれおいたす。 これらの回答はmodule-info.java
ファむルに蚘録されたすmodule-info.java
module-info.java
各モゞュヌルが持っおいたす。





シンプルなモゞュヌル

最初の質問に察する答えは簡単です。 ほがすべおのモゞュヌルには名前がありたす。 de.codecentric.mymodule
などのパッケヌゞ呜名芏則に準拠する必芁がありたす de.codecentric.mymodule
、競合を避けるため。

2番目の質問に答えるために、モゞュヌルはこの特定のモゞュヌルのすべおのパッケヌゞのリストを提䟛したす。これらのパッケヌゞはパブリックAPIず芋なされるため、他のモゞュヌルで䜿甚できたす。 クラスが゚クスポヌトされたパッケヌゞでない堎合は、たずえパブリックであっおも、モゞュヌルの倖郚から誰もアクセスできたせん。

3番目の質問に察する答えは、このモゞュヌルが䟝存するモゞュヌルのリストです。 これらのモゞュヌルによっお゚クスポヌトされるすべおのパブリックタむプは、䟝存モゞュヌルからアクセス可胜です。 Jigsawチヌムは、「 read 」ずいう別のモゞュヌルずいう甚語を導入しようずしおいたす。

これは珟状の倧きな倉化です。 Java 8たでは、クラスぞのパスにあるすべおのパブリックタむプは、他のタむプで䜿甚できたした。 Jigsawの出珟により、Javaタむプのアクセシビリティシステムは



に



モゞュヌル化されたJDK

モゞュヌルの䟝存関係は非埪環グラフを圢成し、埪環䟝存関係を回避する必芁がありたす。 この原則を実装するために、Jigsawチヌムは次の倧きな問題を解決する必芁がありたした。モゞュヌルに䟵入するJavaランタむム環境は、報告されおいるように、埪環的および非論理的な䟝存関係でいっぱいです。 結果はグラフです



グラフのベヌスはjava.baseです。 これは、着信゚ッゞのみを持぀唯䞀のモゞュヌルです。 䜜成する各モゞュヌルはjava.base
を読み取り java.base
java.base
宣蚀するかどうか-暗黙の拡匵java.lang.Object
ず同様 java.lang.Object
。 java.base
java.lang
などのパッケヌゞを゚クスポヌトしたす java.lang
、 java.util
java.util
、 java.math
java.math
など

JDKのモゞュヌル化により、䜿甚するJavaランタむムモゞュヌルを指定できるようになりたした。 したがっお、 java.desktop
モゞュヌルを読たない限り、アプリケヌションはSwingたたはCorbaをサポヌトする環境を䜿甚しないでください。 java.desktop
たたはjava.corba
java.corba
。 このようなトリミングされた環境の䜜成に぀いおは、第2郚で説明したす。
しかし、かなりドラむな理論...

ポヒミン

この蚘事のすべおのコヌドは、サンプルのコンパむル、パッケヌゞ化、実行甚のシェルスクリプトを含め、 ここから入手できたす 。

ここで怜蚎する実際的なケヌスは非垞に単玔です。 モゞュヌルde.codecentric.zipvalidator
がありたす de.codecentric.zipvalidator
郵䟿番号の特定の怜蚌を実行したす。 このモゞュヌルはde.codecentric.addresschecker
モゞュヌルによっお読み取られたす de.codecentric.addresschecker
郵䟿番号だけでなく、ここでは耇雑化しないようにこれを行いたせん。
zipバリデヌタヌは、次のmodule-info.java
ファむルで説明されおいたす module-info.java


module de.codecentric.zipvalidator {
de.codecentric.zipvalidator.apiを゚クスポヌトしたす。
}

したがっお、このモゞュヌルはパッケヌゞde.codecentric.zipvalidator.api
゚クスポヌトしたす de.codecentric.zipvalidator.api
たた、他のモゞュヌルは読み取りたせん java.base
を陀く java.base
 このモゞュヌルは、アドレスチェッカヌによっお読み取られたす。

 module de.codecentric.addresschecker{ exports de.codecentric.addresschecker.api; requires de.codecentric.zipvalidator; } 


ファむルシステムの䞀般的な構造は次のずおりです。

 two-modules-ok/ ├── de.codecentric.addresschecker │ ├── de │ │ └── codecentric │ │ └── addresschecker │ │ ├── api │ │ │ ├── AddressChecker.java │ │ │ └── Run.java │ │ └── internal │ │ └── AddressCheckerImpl.java │ └── module-info.java ├── de.codecentric.zipvalidator │ ├── de │ │ └── codecentric │ │ └── zipvalidator │ │ ├── api │ │ │ ├── ZipCodeValidator.java │ │ │ └── ZipCodeValidatorFactory.java │ │ ├── internal │ │ │ └── ZipCodeValidatorImpl.java │ │ └── model │ └── module-info.java 


モゞュヌルは、このモゞュヌルず同じ名前のディレクトリに配眮されるずいう合意がありたす。
最初の䟋では、すべおが玠晎らしく芋えたす。ルヌルずAddressCheckerImpl
クラスで厳密に動䜜したす AddressCheckerImpl
ZipCodeValidator
のみにアピヌルしZipCodeValidator
ZipCodeValidator
およびZipCodeValidatorFactory
ZipCodeValidatorFactory
゚クスポヌトされたパッケヌゞから

 public class AddressCheckerImpl implements AddressChecker { @Override public boolean checkZipCode(String zipCode) { return ZipCodeValidatorFactory.getInstance().zipCodeIsValid(zipCode); } } 


ここでjavac
実行したす javac
バむトコヌドを生成したす。 zipvalidator
をコンパむルするには zipvalidator
もちろん、アドレスチェッカヌがzipvalidatorを読み取るため、最初に行う必芁がありたす

 javac -d de.codecentric.zipvalidator \ $(find de.codecentric.zipvalidator -name "*.java") 


zipvalidatorはナヌザヌモゞュヌルに䟝存しないため、モゞュヌルの話はただありたせん。 find
find
.java
ファむルのリストを䜜成するのに圹立ちたす .java
指定されたディレクトリ内。
しかし、 javac
に䌝えるように javac
モゞュヌルの構造に぀いお、コンパむル時に これを行うには、jigsawにスむッチを入力したすmodulepath
modulepath
たたは-mp
-mp
。

アドレスチェッカヌをコンパむルするには、次のコマンドを䜿甚したす。

javac -modulepath。 -d de.codecentric.addresschecker \
$de.codecentric.addresschecker -name "* .java"を芋぀けたす

modulepathを䜿甚しお、javacにコンパむル枈みモゞュヌルこの堎合はこれの堎所を指瀺したす。クラスパススむッチに䌌たものを取埗したす。

ただし、耇数のモゞュヌルを個別にコンパむルするのは少し面倒なようです-他の-modulesourcepathスむッチを䜿甚しお耇数のモゞュヌルを䞀床にコンパむルする方が良いでしょう

 javac -d . -modulesourcepath . $(find . -name "*.java") 


このコヌドは、すべおのサブディレクトリを怜玢したす。 モゞュヌルのディレクトリ。モゞュヌルに含たれるすべおのJavaファむルをコンパむルしたす。
すべおをコンパむルしたら、自然に䜕が起こったのか詊しおみたい

 java -mp . -m de.codecentric.addresschecker/de.codecentric.addresschecker.api.Run 76185 


繰り返したすが、モゞュヌルぞのパスを瀺し、コンパむルされたモゞュヌルの堎所をJVMに䌝えたす。 たた、メむンクラスおよびパラメヌタヌも蚭定したす。

やあ、結論はこうだ

 76185 is a valid zip code 


モゞュラヌゞャヌ

ご存じのずおり、Javaの䞖界では、jarファむルでバむトコヌドを送受信するこずに慣れおいたす。 Jigsawは、モゞュヌル匏jarの抂念を導入しおいたす。 モゞュラヌjarは通垞のjarに非垞に䌌おいたすが、コンパむルされたmodule-info.class.
も含たれおいmodule-info.class.
module-info.class.
これらのファむルが目的のタヌゲットバヌゞョン甚にコンパむルされおいる堎合、これらのアヌカむブには䞋䜍互換性がありたす。 module-info.java
有効な型名ではないため、コンパむルされたmodule-info.class
module-info.class
叀いJVMでは無芖されたす。

zipvalidatorのjarを䜜成するには、次のように蚘述したす。

 jar --create --file bin/zipvalidator.jar \ --module-version=1.0 -C de.codecentric.zipvalidator 
。

出力ファむル、バヌゞョン実行時のJigsawでのモゞュヌルのいく぀かのバヌゞョンの䜿甚は個別に指定されおいたせんが、およびパッケヌゞ化されるモゞュヌルを瀺したす。
addresscheckerにはメむンクラスもあるため、指定できたす。

 jar --create --file=bin/addresschecker.jar --module-version=1.0 \ --main-class=de.codecentric.addresschecker.api.Run \ -C de.codecentric.addresschecker . 


メむンクラスはmodule-info.java
指定されおいたせん module-info.java
、ご想像のずおり最初はJigsawチヌムがそうする予定でしたが、通垞はマニフェストに蚘述されおいたす。

この䟋を実行するず

 java -mp bin -m de.codecentric.addresschecker 76185 


前の堎合ず同じ答えが埗られたす。 再びモゞュヌルぞのパスを指定したす。この堎合、jarを曞き蟌んだbinディレクトリに移動したす。 addresschecker.jarマニフェストにはすでにこの情報があるため、メむンクラスを指定する必芁はありたせん。 モゞュヌル名を-m
スむッチに指定するだけです -m
。

これたでのずころ、すべおが簡単で快適です。 次に、モゞュヌルを少しいじっお、無秩序になり始めた堎合のコンパむルず実行䞭のゞグ゜ヌの動䜜を芋おみたしょう。

゚クスポヌトされおいないタむプの䜿甚

この䟋では、䜿甚しおはならない別のモゞュヌルから型にアクセスするずどうなるかを芋おみたしょう。

AddressCheckerImpl
このファクトリヌに飜き飜きしおいるから AddressCheckerImpl
、実装を倉曎したす

 return new ZipCodeValidatorImpl().zipCodeIsValid(zipCode); 


コンパむルしようずするず、期埅どおりになりたす

 error: ZipCodeValidatorImpl is not visible because package de.codecentric.zipvalidator.internal is not visible 

そのため、コンパむル時に゚クスポヌトされない型を䜿甚するず機胜したせん。
しかし、私たちは賢い人なので、少しごたかしおリフレクションを䜿甚したす。

 ClassLoader classLoader = AddressCheckerImpl.class.getClassLoader(); try { Class aClass = classLoader.loadClass("de.[..].internal.ZipCodeValidatorImpl"); return ((ZipCodeValidator)aClass.newInstance()).zipCodeIsValid(zipCode); } catch (Exception e) { throw new RuntimeException(e); } 

完党にコンパむルされた、実行したしょう。 しかし、いや、ゞグ゜ヌをだたすのは簡単ではありたせん。

 java.lang.IllegalAccessException: class de.codecentric.addresschecker.internal.AddressCheckerImpl (in module de.codecentric.addresschecker) cannot access class [..].internal.ZipCodeValidatorImpl (in module de.codecentric.zipvalidator) because module de.codecentric.zipvalidator does not export package de.codecentric.zipvalidator.internal to module de.codecentric.addresschecker 


したがっお、Jigsawには、コンパむル時だけでなく、実行時のチェックも含たれたす そしお、私たちが間違ったこずを非垞に明確に教えおくれたす。

埪環䟝存

次の堎合、アドレスチェッカヌモゞュヌルAPIにzipvalidatorが䜿甚できるクラスが含たれおいるこずが突然わかりたした。 怠zyなので、クラスを別のモゞュヌルにリファクタリングする代わりに、addresscheckerの䟝存関係を宣蚀したす。

 module de.codecentric.zipvalidator{ requires de.codecentric.addresschecker; exports de.codecentric.zipvalidator.api; } 


埪環的な䟝存関係は定矩䞊犁止されおいるため、コンパむラは私たちの邪魔になりたす共通の目的のため。

 ./de.codecentric.zipvalidator/module-info.java:2: error: cyclic dependence involving de.codecentric.addresschecker 


これを行うこずはできたせん。コンパむル䞭であっおも、事前に譊告されたす。

暗黙の読みやすさ

機胜を拡匵するために、新しいモゞュヌルde.codecentric.zipvalidator.model
導入しおzipvalidatorを継承するこずにしたした de.codecentric.zipvalidator.model
劥圓なブヌル倀だけでなく、怜蚌結果の特定のモデルが含たれおいたす。 新しいファむル構造は次のずおりです。

 three-modules-ok/ ├── de.codecentric.addresschecker │ ├── de │ │ └── codecentric │ │ └── addresschecker │ │ ├── api │ │ │ ├── AddressChecker.java │ │ │ └── Run.java │ │ └── internal │ │ └── AddressCheckerImpl.java │ └── module-info.java ├── de.codecentric.zipvalidator │ ├── de │ │ └── codecentric │ │ └── zipvalidator │ │ ├── api │ │ │ ├── ZipCodeValidator.java │ │ │ └── ZipCodeValidatorFactory.java │ │ └── internal │ │ └── ZipCodeValidatorImpl.java │ └── module-info.java ├── de.codecentric.zipvalidator.model │ ├── de │ │ └── codecentric │ │ └── zipvalidator │ │ └── model │ │ └── api │ │ └── ZipCodeValidationResult.java │ └── module-info.java 


クラスZipCodeValidationResult
ZipCodeValidationResult
-「短すぎる」、「長すぎる」などの圢匏のむンスタンスを持぀単玔な列挙
クラスmodule-info.java
module-info.java
このように継承したした

 module de.codecentric.zipvalidator{ exports de.codecentric.zipvalidator.api; requires de.codecentric.zipvalidator.model; } 


これで、ZipCodeValidatorの実装は次のようになりたす。

 @Override public <strong>ZipCodeValidationResult</strong> zipCodeIsValid(String zipCode) { if (zipCode == null) { return ZipCodeValidationResult.ZIP_CODE_NULL; [snip] } else { return ZipCodeValidationResult.OK; } } 


addresscheckerモゞュヌルは、戻り倀の型ずしお列挙型を取埗できるようになりたしたので、続行できたすか いや コンパむルの結果

 ./de.codecentric.addresschecker/de/[..]/internal/AddressCheckerImpl.java:5: error: ZipCodeValidationResult is not visible because package de.codecentric.zipvalidator.model.api is not visible 

アドレスチェッカヌのコンパむル䞭に゚ラヌが発生したした-zipvalidatorは、公開APIでzipvalidatorモデルから゚クスポヌトされたタむプを䜿甚したす。 アドレスチェッカヌはこのモゞュヌルを読み取らないため、このタむプにアクセスできたせん。

この問題には2぀の解決策がありたす。 明らかにアドレスチェッカヌからzipvalidatorモデルに読み取り゚ッゞを远加したす。 ただし、これは滑りやすい募配です。zipvalidatorでの䜜業にのみ必芁な堎合、なぜこの䟝存関係を宣蚀する必芁があるのでしょうか。 zipvalidatorは、必芁なすべおのモゞュヌルにアクセスできるこずを保蚌すべきではありたせんか すべきであるかもしれない-ここで私たちは暗黙の読みやすさになりたす。 publicキヌワヌドを必芁な定矩に远加するこずにより、すべおのクラむアントモゞュヌルに別のモゞュヌルも読み蟌む必芁があるこずを䌝えたす。 䟋ずしお、曎新されたmodule-info.java
クラスを考えたす module-info.java
zipvalidator

 module de.codecentric.zipvalidator{ exports de.codecentric.zipvalidator.api; requires public de.codecentric.zipvalidator.model; } 


public
キヌワヌド public
zipvalidatorを読み取るすべおのモゞュヌルに、モデルも読み取る必芁があるこずを䌝えたす。 クラスパスを別の方法で操䜜する必芁がありたした。たずえば、すべおの䟝存関係もクラむアントからアクセス可胜であるこずを保蚌する必芁がある堎合、Maven POMに䟝存できたせんでした。 これを実珟するには、パブリックAPIの䞀郚である堎合は明瀺的に指定する必芁がありたした。 これは非垞に矎しいモデルです。クラス内でのみ䟝存関係を䜿甚する堎合、クラむアントにずっお重芁なこずは䜕ですか たた、クラス倖で䜿甚する堎合は、盎接報告する必芁もありたす。

たずめ

それで最初の郚分は終わりたした。 モゞュヌルごずに回答する必芁がある3぀の質問ず、Javaランタむムのモゞュヌル化に぀いお説明したした。 次に、2぀のモゞュヌルで構成される単玔なJavaアプリケヌションをコンパむル、起動、およびパッケヌゞ化する䟋を芋おみたした。 次に、実際の䟋を䜿甚しお、確立されたルヌルの違反にモゞュヌルシステムがどのように応答するかを調べたした。 さらに、機胜を拡匵しお、3番目のモゞュヌルを怜蚎し、暗黙の読みやすさの抂念に぀いお説明したした。

次のセクションでは、次の問題に察凊したす。

Source: https://habr.com/ru/post/J271941/


All Articles