پرش به محتوای اصلی
مسیر تخصصی جاوا و Spring
درخواست پروژهارتباط با ماراهنما
جاواپرو v1.2.14یاد بگیر، تمرین کن، حرفه‌ای بساز
خانهدوره‌هاآموزش رایگانوبلاگمدرس‌هاخدمات
خانهمعرفی (JSR 376) JPMS در زبان برنامه نویسی جاوا
وبلاگ »

معرفی (JSR 376) JPMS در زبان برنامه نویسی جاوا

تو این مقاله میخوایم ببینیم JPMS یا همون Java Platform Module System که در جاوا 9 معرفی شد دقیقا چیه.

۶ دقیقه مطالعهوبلاگ »آموزش جاوا و انجام پروژه های برنامه نویسی
معرفی (JSR 376) JPMS در زبان برنامه نویسی جاوا
محتوای منتخب جاواپرو

خلاصه مطلب

تو این مقاله میخوایم ببینیم JPMS یا همون Java Platform Module System که در جاوا 9 معرفی شد دقیقا چیه.
نوع محتوامقاله آموزشی
موضوعوبلاگ »
زمان مطالعه۶ دقیقه
آخرین ویرایش۲۴ فروردین ۱۴۰۳

طبق گفته ی oracle یکی از مهمترین فناوری مهندسی نرم افزار در جاوا ست که نتیجه ای از پروژه ی Jigsaw بوده و کمک میکنه بهره وری پروژه بیشتر بشه.

پروژه ی ماژولار کردن Java از نسخه ی 7 کلید خورد و نهایتا در نسخه ی 9 اضافه شد.

هدف JPMS رفع دو مشکل بزرگ در جاوا بود classpath ها وmonolithic jdk :

در حالت عادی هنگامی که کتابخونه (Jar file) هایی که در خود Jdk موجود نیستند استفاده میکنیم باید با - classpath هنگام ران کردن برنامه ادرسیش رو بدیم. حالا اگر اشتباهی دو تا لایبری با ورژن های متفاوت ادد کرده باشیم چی؟مشکلی به وجود میاد به اسم Jar Hell

خب حالا مشکل این Jar hell چیه؟وقتی یه متدی مثلا از کتابخونه ی x رو فراخوانی کردیم که در ورژن 1 هست ولی در ورژن 2 حذف شده و هر دو توی classpath ادد شدن یکیشون رندوم استفاده میشن! درواقع هنگام کامپایل هیچ خبری نیست ولی موقع ران شدن توی یکسری شرایط به ارور بر میخورید.

وmonolithic jdk چیه؟ کلاس های جاوا به شدت به هم وابستگی داشتن و وقتی یک برنامه ی ساده که مثلا میخواستیم چیزی رو فقط پرینت کنیم (مثلا hello world) باید کل JRE رو روی سیستممون نصب میکردیم مثلا چیزی حدود 50مگابایت فقط برای hello world و حالا اگر برنامه ی سخت افزاری میخواستیم بنویسیم با محدودیت حافظه هم مواجه میشدیم و...

نتیجه ی ماژولار کردن Java بهبود عملکرد خود Jvm هم هست .JSR 376 (Java Specification Requests)

نشون داده که عملکرد بهینه سازی Jvm وقتی که ماژول ها تفکیک شدن و فقط اونایی که لازم هستن اضافه شدن بهبود پیدا کرده

یکی دیگه از مواردی که با JPMS به ارمغان اومده و درواقع از مهمترین اهداف JPMS بود کپسوله سازی قدرتمند تر هست (Strong encapsulation):

پکیج های یک ماژول فقط در صورتی در اختیار دیگر ماژول ها قرار میگیرن که در ماژول به صراحت اعلام بشه میخواد فلان پکیج رو در اختیار دیگر ماژول ها قرار بده ! تازه اوناهم فقط وقتی میتونن ازش استفاده کنن که به صراحت اعلام کنن بهش نیاز دارن.این حرکت کپسوله سازی رو قوی تر میکنه برای مثال کلاس هایی در خود جاوا هست ( internal Api ) که فقط برای APIداخلی JDK طراحی شدن ولی توسط کلاس های خارجی مورداستفاده قرار میگرفتن این قضیه میتونه باعث کاهش امنیت بشه ولی با JPMS این مشکل هم مرتفع شده.

مشاهده ی لیست ماژول های جاوا در سیستم های مختلف :

java--list-modules

و اگه بخوایم اطلاعات یک ماژول رو به دست بیاریم :

java--describe-module java.sql

نحوه ی تعریف module :

ابتدا باید یک فایل به نام module-info.java ایجاد کنید و اون رو در root folder قرار بدید (مثلا پکیج اصلی برنامه هست com.example.myprogram باید خارج از این پکیج و دقیقا کنار پوشه ی com باشه .. درونش نباشه ها فقط توی مسیری باشه که پوشه ی com هست):

module modulename { }

فایل باید به صورت بالا شروع باشه با نام ماژول.

کلمات کلیدی رزرو شده در تعریف ماژول هم اینها هستند:

exports, module, open, opens, provides, requires, uses, with, to transitive.

بریم سراغ توضیح کلمات کلیدی بالا :(کد هارو رو درون اکولادی که بالا تعریف کردیم مینویسیم)

requires modulename;

همینطور که از اسمش مشخصه داره میگه اقای jvm این ماژول من وابستگی داره به فلان ماژول و تو اددش کن به classpath من.

البته برای ماژول هایی که فقط موقع کامپایل نیازشون داریم از حرکت زیر استفاده میکنیم:

requires static modulename;

اما خب دقیقا منظورمون از ماژول هایی که فقط زمان کامپایل نیازشون داریم چیه؟ خیلی از کتابخونه ها فقط زمان کامپایل به کار میان و اصلا قرار نیست زمان رانتایم استفاده بشن (مثل Lombok که درواقع بر اساس annotation هایی که زدیم میاد سورس کد رو تولید میکنه نکته ی مهم اینکه تمام انوتیشن هایی که فقط زمان کامپایل باید در دسترس باشن RetentionPolicy شون CLASS یا SOURCE هست ) این ماژول ها برای زمان رانتایم اختیاری هستن.

یه چیز دیگه داریم به اسم :

requires transitive modulename;

اینم میاد میگه ای کسایی که دارید از ماژول من استفاده میکنید و ای منی که خودم دارم از یه ماژول دیگه استفاده میکنم که کار شمارو انجام بدم.. پس شما بصورت ضمنی داری از اون ماژول منم استفاده میکنی.

فرض کنید یک ماژول Bar دارید که اون داره از ماژول Drink استفاده میکنه و یه همچین کدی هم در نظر بگیرید :

in module _bar_ public class Bar { `Drink` comes from the module _drink_, which _bar_ requires public Drink buyDrink() { * ... * } }

حالا اگر ماژولی به نام customer که داره از Bar استفاده میکنه بیاد متد buyDrink رو کال کنه خطای کامپایل رخ میده با این منطق که ماژول customer به ماژول Drink دسترسی نداره و باید با استفاده از requiers Drink; توی فایل Module-info خودش مشخص کنه . اما راه حل منطقی تر اینه :مایی که کتابخونه نوشتیم باید تمام این داستانارو گردن بگیریم و بگیم هرکس از ما استفاده کرد درواقع از فلان ماژول هم استفاده کرده. پس توی فایل module-info ای که در ماژول Bar هست مینویسیم:

requires transitive drink;

حالا اگر بخوایم مشخص کنیم ماژول ما فقط برای بعضی ماژولای دیگه قابل مشاهده باشه چی ؟(بهش میگن qualified export) خیلی راحت میایم از exports...to استفاده میکنیم :

exports modulename;

حالا اگر بخوایم مشخص کنیم ماژول ما فقط برای بعضی ماژولای دیگه قابل مشاهده باشه چی ؟(بهش میگن qualified export) خیلی راحت میایم از exports...to استفاده میکنیم :

exports mymodulename to othermodulename;
exports mymodulename to othermodulename2;
exports mymodulename to othermodulename3;

میدونیم که توسط رفلکشن (reflection) اعضای private کلاس و... قابل دسترسیه ولی توی jpms این خبرا نیست باید اجازه بدیم که ماژول دیگری ایا میتونه توسط رفلکشن از ماژول ما استفاده کنه یا نه:

opens mymodulename;

و اگر بخوایم فقط برای یک ماژول خاص باشه مثل exports...to از opens...to استفاده میکنیم.

مثال opens رو میتونیم توی یک پروژه ی جاوا اف ایکسی که داخل fxml اومدیم برای یک ویو fx:id تنظیم کردیم و توی کنترل با انوتیشن @FXML اون رو گرفتیم. این حرکت با reflection انجام میشه و باید حتما ماژولمون برای javafx.fxml چی باشه؟افرین ! opens باشه:

opens mymodule to javafx.fxml;

اگر کمی دقت کنید دیگه ما برای کپسوله سازی فقط با private, protected ,public, package طرف نیستیم بلکه با پابلیکی که فقط برای ماژول ما پابلیکه. پابلیکی که برای همه ی ماژول ها پابلیکه و پابلیکی که برای بعضی ماژول ها پابلیک هم طرف هستیم که این دقیقا میشه همون Strong encapsulation

دو مورد دیگه میمونه به نام uses و provides..with که مربوط میشه به ServiceLoader که خواندنش رو به خودتون واگذار میکنم .

در مطلب بعدی اینکه چطور با ماژولاریتی کردن پروژه میتونیم یک JDKسفارشی بسازیم که حجمش فقط بر اساس ماژول های مورد نیاز ما باشه صحبت میکنیم.

منابع :

Openjfx jigsaw

Understanding Java 9 Modules

Javaland

برچسب‌هاوبلاگ »دنیای برنامه نویسی »جاوابرنامه نویسی جاوازبان برنامه نویسی جاواJPMSJava Platform Module Systemجاوا 9هدف JPMSJPMS چیستآموزش جاواویژگی جاوا 9ماژولار کردن Javaبرنامه نویسی
ادامه مسیر

پیشنهاد جاواپرو

موضوع را با آموزش‌های مرتبط ادامه دهید و نکته‌های کاربردی را در مسیر خود نگه دارید

مشاهده دوره‌ها
مطالب پیشنهادی

ادامه مطالعه

xدسته‌بندی نشده
۱۱ دی ۱۳۹۸ مطالعه کوتاه

x

پادکست شماره 3 – راه های کسب درآمد از برنامه نویسی

مطالعه مطلب
پادکست شماره 3 - راه های کسب درآمد از برنامه نویسیپادکست
۲۹ اردیبهشت ۱۴۰۴ مطالعه کوتاه

پادکست شماره 3 - راه های کسب درآمد از برنامه نویسی

در این پادکست برنامه نویسی به شیوه ها و راه های کسب درآمد از برنامه نویسی پرداخته ایم. یک کاغذ و قلم بردارید و به پادکست گوش بدید.

مطالعه مطلب
پادکست شماره 2 - چگونه وارد فضای برنامه نویسی شویم؟پادکست
۲۹ اردیبهشت ۱۴۰۴ مطالعه کوتاه

پادکست شماره 2 - چگونه وارد فضای برنامه نویسی شویم؟

در این پادکست برنامه نویسی یاد میگیریم که چگونه وارد فضای برنامه نویسی شویم و تخصص برنامه نویسی را به دست آوریم.

مطالعه مطلب
جاواپرومرجع تخصصی یادگیری و توسعهٔ جاوا

تجربه‌ای منظم، ساده و حرفه‌ای برای یادگیری عمیق جاوا، Spring و مهندسی نرم‌افزار؛ قابل استفاده در موبایل، تبلت و دسکتاپ

یادگیری

همه دوره‌هاآموزش رایگانمسیر یادگیریمدرس‌ها

جاواپرو

درباره ماخدمات تخصصیدرخواست پروژهبلاگ فنی

پشتیبانی

تماس با ماپرسش‌های متداولقوانین و حریم خصوصیبروزرسانی‌های جاواپروثبت تیکت
خرید امنپرداخت فقط در درگاه رسمیپشتیبانی آموزشیمسیر ارتباط شفاف و پیگیری‌پذیردسترسی پایداروب‌اپ واکنش‌گرا روی همه دستگاه‌ها
© ۱۴۰۵ جاواپرو؛ همه حقوق محفوظ استتوسعه توسط پایاپینگ
خانهدوره‌هاسبد