برنامههای جاوا بهعنوان WORA (یکبار بنویس، همهجا اجرا کن) شناخته میشوند. این بدان معناست که یک برنامهنویس میتواند کد جاوا را روی یک سیستم بنویسد و بدون نیاز به تغییر، آن را روی هر سیستم دیگری که از جاوا پشتیبانی میکند، اجرا کند. این قابلیت، به لطف JVM امکانپذیر شده است.
وقتی یک فایل .java را کامپایل میکنیم، کامپایلر جاوا فایلهای .class که شامل بایتکد هستند را ایجاد میکند. این فایلهای .class دقیقاً همان نام کلاسهای تعریفشده در فایل.java را دارند. هنگامی که این فایل اجرا میشود، مراحل مختلفی را طی میکند که در مجموع، عملکرد JVM را توضیح میدهند.

1- زیرسیستم بارگذاری کلاس (Class Loader Subsystem)
این زیرسیستم عمدتاً مسئول سه فعالیت است:1. بارگذاری (Loading)
2. پیونددهی (Linking)
3. مقدمهسازی (Initialization)
بارگذاری (Loading) :
بارگذار کلاس (Class Loader) فایل.class را میخواند، دادههای دودویی (Binary Data) مربوطه را تولید کرده و آن را در منطقه متد (Method Area) ذخیره میکند. برای هر فایل .class ، JVM اطلاعات زیر را در منطقه متد نگهداری میکند:
• نام کامل و مشخص کلاس بارگذاریشده و کلاس والد مستقیم آن.
• مشخص میکند که فایل.class مربوط به یک کلاس، اینترفیس (Interface) یا enum است.
• اطلاعات مربوط به تعدیلکنندهها (Modifiers)، متغیرها و متدها.
// A Java program to demonstrate working
// of a Class type object created by JVM
// to represent .class file in memory.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// Java code to demonstrate use
// of Class object created by JVM
public class Test {
public static void main(String[] args)
{
Student s1 = new Student();
// Getting hold of Class
// object created by JVM.
Class c1 = s1.getClass();
// Printing type of object using c1.
System.out.println(c1.getName());
// getting all methods in an array
Method m[] = c1.getDeclaredMethods();
for (Method method : m)
System.out.println(method.getName());
// getting all fields in an array
Field f[] = c1.getDeclaredFields();
for (Field field : f)
System.out.println(field.getName());
}
}
// A sample class whose information
// is fetched above using its Class object.
class Student {
private String name;
private int roll_No;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getRoll_no() { return roll_No; }
public void setRoll_no(int roll_no)
{
this.roll_No = roll_no;
}
}
Student
getName
setName
getRoll_no
setRoll_no
name
roll_No
Note: For every loaded “.class” file, only one object of the class is created.
Student s2 = new Student();
// c2 will point to same object where
// c1 is pointing
Class c2 = s2.getClass();
System.out.println(c1==c2); // true
پیونددهی (Linking)
فرآیند پیونددهی شامل سه مرحله اصلی است:1. تأیید (Verification)
2. آمادهسازی (Preparation)
3. تبدیل مراجع (Resolution) - اختیاری
1- تأیید (Verification):
این مرحله صحت و درستی فایل.class را بررسی میکند. به این معنا که بررسی میشود آیا این فایل بهدرستی قالببندی شده و توسط یک کامپایلر معتبر تولید شده است یا خیر.• اگر این بررسی ناموفق باشد، JVM یک استثنا در زمان اجرا با نام java.lang.VerifyError ایجاد میکند.
• این وظیفه توسط ByteCodeVerifier انجام میشود.
• پس از موفقیت در این مرحله، فایل کلاس آماده کامپایل میشود.
2- آمادهسازی (Preparation):
• JVM حافظهای را برای متغیرهای استاتیک کلاس اختصاص میدهد.• حافظه تخصیصیافته را با مقدار پیشفرض مقداردهی اولیه میکند.
3- تبدیل مراجع اختیاری (Resolution):
• در این مرحله، مراجع نمادین (Symbolic References) به مراجع مستقیم (Direct References) تبدیل میشوند.• این کار با جستوجو در منطقه متد (Method Area) برای یافتن موجودیتهای مرجعشده انجام میشود.
مقدمهسازی (Initialization)
در این مرحله، تمام متغیرهای استاتیک با مقادیر مشخصشده در کد و بلوک استاتیک (static block) (در صورت وجود) مقداردهی میشوند.• این مقداردهی به ترتیب از بالا به پایین در داخل کلاس انجام میشود.
• در سلسلهمراتب کلاسها، مقداردهی از کلاس والد به کلاس فرزند صورت میگیرد.
انواع بارگذارهای کلاس (Class Loaders):
بهطور کلی، سه نوع بارگذار کلاس در JVM وجود دارد:1- بارگذار بوتاسترپ (Bootstrap Class Loader)
• هر پیادهسازی JVM باید یک Bootstrap Class Loader داشته باشد که قادر به بارگذاری کلاسهای معتبر و مورد اعتماد باشد.
• این بارگذار، کلاسهای اصلی API جاوا را که در مسیر "JAVA_HOME/lib" قرار دارند، بارگذاری میکند.
• این مسیر معمولاً به نام Bootstrap Path شناخته میشود.
• این بارگذار به زبانهای Native مانند C و C++ پیادهسازی شده است.
2- بارگذار افزونهها (Extension Class Loader)
• این بارگذار، فرزند Bootstrap Class Loader است.
• کلاسهایی که در دایرکتوری افزونهها (JAVA_HOME/jre/lib/ext) یا هر دایرکتوری دیگری که توسط ویژگی سیستم java.ext.dirs مشخص شده باشد را بارگذاری میکند.
• این بارگذار در جاوا و توسط کلاس sun.misc.Launcher$ExtClassLoader پیادهسازی شده است.
3- بارگذار سیستم/برنامه (System/Application Class Loader)
• این بارگذار، فرزند Extension Class Loader است.
• مسئول بارگذاری کلاسها از مسیر کلاس برنامه (Application Classpath) میباشد.
• این بارگذار از متغیر محیطی java.class.path برای جستوجوی کلاسها استفاده میکند.
• در جاوا و توسط کلاس sun.misc.Launcher$AppClassLoader پیادهسازی شده است.

// Java code to demonstrate Class Loader subsystem
public class Test {
public static void main(String[] args)
{
// String class is loaded by bootstrap loader, and
// bootstrap loader is not Java object, hence null
System.out.println(String.class.getClassLoader());
// Test class is loaded by Application loader
System.out.println(Test.class.getClassLoader());
}
}
Output
null
jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f
Note: JVM follows the Delegation-Hierarchy principle to load classes. System class loader delegate load request to extension class loader and extension class loader delegate request to the bootstrap class loader. If a class found in the boot-strap path, the class is loaded otherwise request again transfers to the extension class loader and then to the system class loader. At last, if the system class loader fails to load class, then we get run-time exception java.lang.ClassNotFoundException.
2- بارگذارهای کلاس (Class Loaders)
در JVM، سه نوع اصلی بارگذار کلاس وجود دارد:1. بارگذار بوتاسترپ (Bootstrap Class Loader)
• کلاسهای هستهای API جاوا را از مسیر "JAVA_HOME/lib" بارگذاری میکند.
• به زبان Native مثل C یا C++ پیادهسازی شده است و یک شیء جاوا نیست.
2. بارگذار افزونهها (Extension Class Loader)
• کلاسها را از مسیر "JAVA_HOME/jre/lib/ext" یا هر مسیر مشخصشده در ویژگی java.ext.dirs بارگذاری میکند.
• در جاوا پیادهسازی شده است.
3. بارگذار سیستم/برنامه (System/Application Class Loader)
• کلاسها را از مسیر کلاس برنامه (Application Classpath) بارگذاری میکند.
• مسیر کلاس برنامه توسط متغیر محیطی java.class.path مشخص میشود.
• این بارگذار نیز در جاوا پیادهسازی شده است.
Example:
public class Test {
public static void main(String[] args) {
System.out.println(String.class.getClassLoader());
System.out.println(Test.class.getClassLoader());
}
}
3- نواحی حافظه JvM (JVM Memory Areas)
JVM از چندین ناحیه حافظه برای مدیریت دادهها و اجرای برنامهها استفاده میکند:- ناحیه متد (Method Area)
• در این ناحیه، اطلاعات سطح کلاس مانند نام کلاس، نام کلاس والد، اطلاعات متدها و متغیرها ذخیره میشود.
• متغیرهای استاتیک نیز در این قسمت ذخیره میشوند.
• تنها یک ناحیه متد برای هر JVM وجود دارد و یک منبع اشتراکی است.
- ناحیه هیپ (Heap Area)
• اطلاعات مربوط به همه اشیاء (Objects) در این ناحیه ذخیره میشود.
• تنها یک ناحیه هیپ برای هر JVM وجود دارد.
• این ناحیه نیز یک منبع اشتراکی است.
- ناحیه استک (Stack Area)
• برای هر رشته (Thread)، JVM یک پشته زمان اجرا (Run-time Stack) ایجاد میکند که در این ناحیه ذخیره میشود.
• هر بلوک از این پشته یک رکورد فعال (Activation Record) یا فریم پشته (Stack Frame) نام دارد که شامل فراخوانی متدها است.
• تمام متغیرهای محلی متدها در فریم مربوطه ذخیره میشوند.
• پس از پایان اجرای یک Thread، پشته مربوطه توسط JVM حذف میشود.
• این ناحیه یک منبع اشتراکی نیست (هر Thread پشته خاص خود را دارد).
-ثباتهای شمارنده برنامه (PC Registers)
• آدرس دستورالعمل در حال اجرا از یک Thread را ذخیره میکند.
• هر Thread دارای PC Register مخصوص به خود است.
- پشته متدهای بومی (Native Method Stacks)
• برای هر Thread، یک پشته بومی (Native Stack) جداگانه ایجاد میشود.
• این پشته اطلاعات مربوط به متدهای بومی (Native Methods) را ذخیره میکند.

4- موتور اجرا (Execution Engine)
موتور اجرا وظیفه اجرای فایل.class بایتکد را بر عهده دارد.• این موتور بایتکد را خطبهخط میخواند و از دادهها و اطلاعات ذخیرهشده در نواحی مختلف حافظه استفاده کرده و دستورات را اجرا میکند.
• موتور اجرا را میتوان به سه بخش اصلی تقسیم کرد:
- مفسر (Interpreter)
• بایتکد را خطبهخط تفسیر و اجرا میکند.
• عیب: اگر یک متد چندین بار فراخوانی شود، هر بار نیاز به تفسیر مجدد دارد که باعث کاهش سرعت اجرا میشود.
-کامپایلر همزمان (Just-In-Time Compiler - JIT)
• برای افزایش کارایی مفسر استفاده میشود.
• کل بایتکد را کامپایل کرده و آن را به کد محلی (Native Code) تبدیل میکند.
• زمانی که مفسر متوجه فراخوانیهای مکرر یک متد شود، JIT مستقیماً کد محلی (Native Code) را ارائه میدهد و نیازی به تفسیر مجدد نیست، که باعث بهبود کارایی میشود.
- جمعآوری زباله (Garbage Collector)
• اشیایی را که دیگر ارجاعی به آنها وجود ندارد، از بین میبرد.
• برای اطلاعات بیشتر درباره Garbage Collector، میتوان به منابع تخصصیتر مراجعه کرد.
۵- رابط بومی جاوا (Java Native Interface - JNI)
JNI یک رابط (Interface) است که با کتابخانههای متدهای بومی (Native Method Libraries) ارتباط برقرار میکند و کتابخانههای بومیC، C++ موردنیاز برای اجرا را فراهم میسازد.• این رابط به JVM این امکان را میدهد که:
• کتابخانههای C/C++ را فراخوانی کند.
• توسط کتابخانههای C/C++ که ممکن است به سختافزار خاصی وابسته باشند، فراخوانی شود.
6- کتابخانههای متدهای بومی (Native Method Libraries)
• مجموعهای از کتابخانههای بومی هستند که برای اجرای متدهای بومی استفاده میشوند.
• این کتابخانهها معمولاً به زبانهایی مانند C و C++ نوشته شدهاند.
نتیجهگیری
JVM یک جزء کلیدی از زبان برنامهنویسی جاوا است که اجرای بایتکد را مستقل از پلتفرم ممکن میسازد. با ساختاری متشکل از بارگذار کلاس (Class Loader)، مناطق حافظه (Memory Areas)، موتور اجرا (Execution Engine) و رابط بومی جاوا (JNI)، JVM امکان اجرای کارآمد و بهینه برنامههای جاوا را فراهم میکند.اگر تجربهای در بهینهسازی عملکرد JVM یا استفاده از تکنیکهای پیشرفته مانند JIT و Garbage Collector دارید، نظرات و تجربیات خود را در بخش کامنتها با ما به اشتراک بگذارید. 👇
ورود و ثبت نام برای ارسال نظر وارد شوید