خب یکی از موارد خیلی مهم در جاوا تفاوت متغیرهای References Types با Value Types هستش. برای فهم بهتر این موضوع، در مورد چند موضوع دیگر هم باید توضیح بدم.
مقدمه
بعد از فعال شدن JVM، مقداری از حافظه (رم) در اختیار این ماشین مجازی قرار میگیرد. وقتی که JVM رو ران میکنیم، یک بخش دیگر از حافظه در اختیار این ماشین مجازی قرار میگیرد که شامل ۲ بخش Stack و Heap میشود. فهم درست این ۲ حافظه و مفهوم Garbage Collection در جاوا بسیار میتونه در آینده برای ما مفید باشه.
حافظه Stack چیست؟
نمیدونم توی بحث ساختمان دادهها (که تصمیم دارم بعد از تموم شدن آموزشهای جاوا به اون بپردازم) با مفهوم Stack مواجه شدین یا خیر. به طور ساده بخوام توضیح بدم، Stack یا پشته مثل دستهای بشقاب هستن که روی هم قرار گرفتن. هر موقع بخواهیم یه مقدار رو قرار بدیم در این حافظه ، معمولا یه بشقاب میزاریم روی این بشقابها (Push) و هر موقع بخواهیم از این دسته مقداری رو برداریم، همیشه بشقاب بالایی رو بر میداریم (Pop). این دسته بشقاب رو به طور کلی توی ساختماندادهها بهش میگن Stack . توی این مثال نوع Stack ما LIFO که مخفف LastIn-FirstOut هستش نام داره.
بر اساس تعریفی که JVM داره، هر موقع که یک Thread (این رو هم به زودی توضیح میدم که چی هستش) شروع به کار میکنه، یک مقدار حافظه به اون اختصاصی داده میشه که بهش Stack گفته میشه. این حافظه متغیرهای محلی و نتایج محلی مربوط به Thread رو درون خودش نگه میداره. برای تعیین مقادیر این حافظه از کلیدهای XSS برای تردها و XX:MaxPermSize برای توابع استفاده میشه. این حافظه در فراخوانی متدها هم مورد استفاده قرار میگیره. وقتی یک Thread جدید در حال اجرا باشه و یا محاسبات Thread به حافظهی بیشتری نیاز داشته باشه و مقدار حافظه ما امکانش رو نداشته باشه، خطای StackOverflowError رو میده. (با Try – Catch کنترل میشه) حافظه Stack در جاوا دارای ۲ بخش میباشد:
۱. method area (-XX)
مواردی مثل توابع، آدرس به مقدار اشیا (متغیرهای رفرنس)، متغیر های پریمیتیو درون توابع از جمله مواردی هستند که در این بخش از حافظه Stack نگهداری میشوند. بعد از واکشی هر استک فریم خود به خود حذف میشوند.
۲. native area (-Xss)
فضای اختصاصی ترد ها (java thread stack size) در این بخش از حافظه Stack نگهداری میشود.
حافظه Heap چیست؟
در جاوا، وقتی یک شی جدید میسازیم و یا به طور کلی از کلمه کلیدی new استفاده میکنیم، یک ناحیه در Heap برای شی ایجاد میشه. متغیرهای Private درون بلاک کلاس هم در heap ذخیره میشن. در صورتی که موقع اجرای برنامه به حافظهی بیشتری نیاز داشته باشیم و اون رو در اختیار نداشته باشه سیستم و امکان تخصیص وجود نداشته باشه، خطای OutOfMemoryError رو میده (با Try – Catch کنترل میشه) . به طور پیشفرض این مقدار ماکزیمم برابر 64mb هستش. ولی میشه از طریق پارامتر -Xmx اون رو تغییر داد. حافظهی heap هم مثل stack شامل ۲ بخش هستش:
۱.initial heap (Xms)
ماشین مجازی جاوا یک فضای اولیه برای حافظه Heap در نظر می گیره که می توان این مقدار را با استفاده از پارامتر -Xms مشخص کرد.
۲.Jvm Max Heap (-Xmx)
در صورتی که JVM نیاز به فضای حافظه Heap بیشتری داشته باشد، JVM بصورت خودکار حافظه Heap را افزایش می دهد و می تواند آن را تا مقدار maximum مورد نظر بالا ببرد.
حافظه Heap شامل کد برنامه، مثل مقدار درون رفرنس ها یا به عبارتی اشیاء که رفرنس آنها در استک قرار دارد، توابع، فیلد ها و داده های استاتیک می باشد. این قسمت از حافظه است که توسط Garbage Collection جاوا به صورت خودکار پاک سازی میشوند. در JRE 32bit ، تنها از ۲GB حافظه پشتیبانی می شود که از این مقدار تنها ۱GB از آن برای Heap قابل مقدار دهی است. (که این مقدار وابسته به سیستم عامل ممکن است حتی تا ۵۱۲MB نیز کم شود. زمانی که خطای Invalid maximum heap size رخ می دهد بدین معنی است که مقدار حافظه heap درخواستی در حال حاضر برای تخصیص به JVM موجود نیست (سیستم عامل حافظه رم کافی ندارد).
خب حالا یه خورده ساده تر توضیح میدم heap و stack رو. ۲ نوع متغیر رو در نظر بگیرید و ۲ تا فضای heap و stack رو:
int a = 20; int b[] = new int[5]; b[0] = 1; b[1] = 2; b[2] = 3; b[3] = 4; b[4] = 5;
مقدار int a = 20 در stack ذخیره میشه ولی در مورد آرایه b ، چون از new استفاده کردیم، مقدارید ۱ و ۲ و ۳و ۴ و ۵ توی heap ذخیره میشه و آدرس این خونه که مقادیر رو داره توی Stack ذخیره میشه شکل زیر رو ببینید:
خب حالا در عکس بالا میبینید که object 1 و object 2 وصل هستن و یه تعدادی اطلاعات هستن داخل heap که به چیزی وصل نیستن. کار Garbage Collection این هستش که بیادش این موارد رو پاک کنه تا حافظه شما خالی بشه.
معمولا این عمل در ۳ حالت شروع به کار میکنه:
عمل read/write در حافظه سیستم بکندی صورت میگیره.
برنامه/اسکریپت کارش تموم شده و می خواد بسته بشه.
بصورت دستی صدا زه بشه (مثل IDE های Netbeans, Eclipse زبان Java, PHP5.3 و…).
خب حالا میرسیم به بحث اصلیمون، یعنی تفاوت References Types با Value Types در جاوا .
حالا میتونیم خیلی راحت تعریف کنیم این ۲ تا رو. متغیرهایی که در stack ذخیره میشن رو Value Type بهش میگن و متغیرهایی که از Heap استفاده میکنند رو References Types میگن بهشون.
دیدگاهتان را بنویسید