ماشین مجازی جاوا چیست؟


در این آموزش قصد داریم تا به تفصیل مفهوم Java Virtual Machine یا به اختصار JVM به معنی «ماشین مجازی جاوا» را مورد بررسی قرار دهیم که در راستای تحقق شعار طراحان این زبان ابداع شده است به طوری که چنین قابلیتی جز با به‌کارگیری مفهومی تحت عنوان جِی‌وی‌اِم امکان‌پذیر نمی‌باشد. در واقع، از بدو ایجاد زبان برنامه‌نویسی جاوا شعار طراحان این زبان مفهومی است که بر اساس آن گفته می‌شود «!Write One, Run Anywhere» بدین معنی که «یک بار برنامۀ جاوای خود را بنویسید سپس روی هر پلتفرمی که خواستید آن را اجرا کنید!» که چنین قابلیتی صرفاً با به‌کارگیری جِی‌وی‌اِم فراهم شده است. به طور کلی، سازوکار ماشین مجازی جاوا را می‌توان در قالب تصویر زیر نشان داد:

همان‌طور که در تصویر بالا مشخص است، برنامۀ جاوایی که می‌نویسیم یا همان سورس‌کد برنامه ابتدا توسط این زبان اصطلاحاً Compile می‌شود که در اینجا منظور از کامپایل شدن یک برنامه تبدیل کدهای جاوای آن به Bytecode است. پس از کامپایل سورس‌کد نوشته‌شده به زبان جاوا، حال وظیفۀ ماشین مجازی است که برنامهٔ اصطلاحاً Compiled (کامپایل‌شده) را به شکلی قابل‌فهم برای پلتفرم مد نظر تبدیل نماید؛ به عبارت دیگر، ماشین‌های مجازی تمام تلاش خود را به کار می‌گیرند تا از روی سورس‌کدی یکسان نتایج نسبتاً یکسانی را از اجرای آن‌ها روی پلتفرم‌های مختلف به دست آورند.

همان‌طور که در تصویر فوق ملاحظه می‌کنید، ماشین مجازی جاوا را می‌توان به عنوان یک لایۀ مجازی مابین برنامۀ نوشته‌شده به زبان جاوا و سیستم‌عامل مد نظر تلقی کرد مضاف بر اینکه می‌توان گفت ماشین مجازی جاوا هیچ گونه عملیاتی روی سورس‌کد اصلی انجام نمی‌دهد بدین معنی که برنامۀ مذکور در ابتدا کامپایل شده و در طی این پروسه به بایت‌کد تبدیل می‌شود تا برای سیستم‌عامل مد نظر قابل‌فهم باشد سپس این بایت‌کدها به ماشین مجازی داده می‌شوند تا برای سیستم‌عامل‌های مختلف بهینه گردند (در آموزش بعدی با مفهوم بایت‌کد و نحوۀ کامپایل یک برنامۀ جاوا به منظور تبدیل به بایت‌کد آشنا خواهیم شد.)

نکته
ماشین مجازی جاوا علاوه بر قابلیت‌های بسیاری که در اختیار برنامه‌نویسان قرار می‌دهد، محدودیت‌هایی را هم ایجاد می‌کند که البته این محدودیت‌ها به نوعی راه‌گشا هستند چرا که منجر به ارتقاء امنیت نرم‌افزارهای نوشته‌شده با جاوا می‌شوند؛ به عبارت دیگر، با به‌کارگیری جِی‌وی‌اِم دولوپرها به هیچ وجه نمی‌توانند بخشی از حافظۀ اختصاص‌یافته به دیگر قسمت‌های برنامه را به زور تصاحب کنند تا بدین طریق بتوانند مثلاً آبجکتی جدید ساخته و فضای حافظه را به آن اختصاص دهند.

یکی از مزایای کامپایل سورس‌کد و تبدیل آن به بایت‌کد این است که بدین طریق می‌توان از دیگر زبان‌های برنامه‌نویسی نیز در توسعۀ اپلیکیشن‌های نوشته‌شده به زبان جاوا استفاده کرد؛ به عبارت دیگر، چنانچه یک زبان برنامه‌نویسی قابلیتی داشته باشد که بتوان در ابتدا سورس‌کد مد نظر را کامپایل کرده و آن را به بایت‌کدی قابل‌فهم برای جاوا تبدیل کرد، در چنین شرایطی ماشین مجازی جاوا امکان اجرای آن بخش از کد که به زبان دیگری نوشته شده است را در کنار کدهای جاوا دارا است.

آشنایی با مفهوم Garbage Collection

منظور از چنین اصطلاحی در زبان برنامه‌نویسی جاوا این است که برنامه‌نویس نیازی به درگیر کردن خود با مسائل مربوط به Memory یا حافظه ندارد چرا که این مسئولیت بر عهدۀ خود ماشین مجازی جاوا گذاشته شده است. در واقع، حافظه در برنامه‌های جاوا به دو قسمت تقسیم می‌شود که عبارتند از حافظۀ Heap و حافظۀ Stack که در صورت ایجاد آبجکتی از روی یکی از کلاس‌های برنامه، آبجکت ساخته‌شده در حافظۀ هیپ ذخیره می‌شود (در آموزش‌های آینده با مفهوم آبجکت، کلاس و نحوۀ ساخت آبجکت از روی آن آشنا خواهیم شد.) حال برای روشن شدن نحوۀ عملکرد Garbage Collector در این زبان، مثالی را مد نظر قرار می‌دهیم بدین صورت که اگر بخواهیم آبجکتی از روی کلاس String بسازیم خواهیم داشت:

String str = new String();

در کد فوق، آبجکتی از روی کلاس String تحت عنوان str ساخته‌ایم و در ادامه آبجکت مذکور در جایی از برنامه مورد استفاده قرار می‌گیرد و چنانچه این آبجکت پس از مدتی در روند اجرای برنامه به کار گرفته نشود، به نوعی آبجکتی مُرده به حساب می‌آید.

در واقع، زبان‌هایی مانند سی‌پلاس‌پلاس قابلیت حذف آبجکت‌های مُرده را نداشته و این امر به صورت دستی و توسط برنامه‌نویسان انجام می‌شود که چنین کاری در برنامه‌های بزرگ و پیچیده به علت تعاملات متعددی که آبجکت‌ها با یکدیگر دارند به فرآیندی بسیار سخت، پیچیده و پُرخطا مبدل می‌گردد در حالی که زبان جاوا چنین قابلیتی را دارا بوده و با به‌کارگیری گاربج کالکتور آبجکت‌های مُرده را از حافظۀ هیپ حذف می‌کند. در حقیقت، گاربج کالکتور بخشی از ماشین مجازی جاوا است و الگوریتم‌های پیچیده‌ای دارد که بدین ترتیب به صورت خودکار و دوره‌ای به حافظۀ هیپ مراجعه کرده و آبجکت‌های مُرده را از آن پاک می‌کند تا فضای حافظه به منظور نگهداری سایر آبجکت‌ها آزاد گردد.

نکته
لازم به یادآوری است که دولوپرهای جاوا نیز می‌توانند به صورت دستی اقدام به فراخوانی گاربج کالکتور کنند اما چنین کاری هرگز توصیه نمی‌شود.

نکتۀ قابل‌توجه در رابطه با مثال فوق این است که متغیر str در این مثال خود یک شیئ نبوده بلکه ارجاعی به آبجکت ساخته‌شده از روی کلاس مذکور در حافظۀ هیپ است و از همین روی می‌توان گفت که متغیر str در حافظۀ اِستک ذخیره شده است (در زبان برنامه‌نویسی جاوا مفهومی تحت عنوان اشاره‌گر وجود ندارد اما در این قسمت می‌توان گفت که str یک نوع اشاره‌گر است چرا که به آبجکت ساخته‌شده از روی کلاس String در حافظۀ هیپ اشاره می‌کند.)

لیست نظرات
کاربر میهمان
دیدگاه شما چیست؟
کاربر میهمان
gsaadati55 قاسم سعادتی
gsaadati55 قاسم سعادتی
۱۳۹۷/۰۴/۲۹
این بخش هم خیلی عالی بود واقعا جای تشکر فراوان داره.
کاربر میهمان
کاربر میهمانمن یک کاربر مهمان هستم
۱۳۹۷/۰۲/۲۷
با سلام و تشکر
تا اینجا به نظرعالی است ، هرچند که عملی هیچگونه کاری انجام نذاده ام ، مطمئنا ادا مه میدم و قبلا هم تشکر میکنم از مطالب بعدی!
amin
amin
۱۳۹۶/۰۴/۰۴
تا اینجای کار که تا حالا عالی است پس ادامه به یادگیری.
fighter
fighter
۱۳۹۶/۰۳/۲۵
bravo
کاربر میهمان
منمن یک کاربر مهمان هستم
۱۳۹۵/۰۷/۱۸
سلام
واقعا ممنون....من یک برنامه نویس مبتدی هستم و اکیر کتابا رو نهایتا یک فصل می خوندم و نمی فهمیدم ولی آموزشای شما واقعا عالین.......
saeedprz
saeedprz
۱۳۹۵/۰۶/۲۹
بی نظیر. خیلی از ابهامات یک ساله که هیچ منبعی جواب قابل فهم نداشت رو دستگیرم کرد. تشکر فراوان
کاربر میهمان
ناشناسمن یک کاربر مهمان هستم
۱۳۹۵/۰۶/۰۱
با سلام ،
باتشکر از آموزش های خوبتون ، لطفا دوره های موجود در سایت رو به اتمام برسونید ، موفق و مؤید باشید ، بدرود.
parisan
parisan
۱۳۹۵/۰۵/۱۳
سلام
ممنون از اموزش های عالی تون و خسته نباشید:)
shivap
shivap
۱۳۹۵/۰۵/۰۶
خیییییلی خوووبه
علی یعقوبی
علی یعقوبی
۱۳۹۵/۰۴/۱۴
خیـلی خوبه که آموزشا رایگانند. واقعا ممنون.