جاوا بایت کد
جاوا بایت کد (به انگلیسی: Java bytecode) مجموعه دستورالعملهای ماشین مجازی جاوا یا به اختصار JVM است.
ارتباط با جاوا
یک برنامهنویس جاوا نیازی به دانستن یا درک جاوا بایت کد ندارد. با این حال، همانطور که در مجله IBM developerWorks پیشنهاد شدهاست، «درک بایت کد و آنچه که توسط کامپایلر جاوا تولید میشود، به برنامه نویس جاوا کمک میکند همانطور که دانش اسمبلی(Assembly) به برنامه نویس C یا C ++ کمک میکند.»
مجموعه دستورالعمل معماری
جی وی ام(JVM) هم یک ماشین پشته ای (به انگلیسی: stack machine) و هم یک ماشین ثبات (به انگلیسی: register machine) است. هر فریم برای یک فراخوانی تابع دارای یک "پشته عملوند" و یک آرایه از "متغیرهای محلی" است. پشته عملوند برای عملوندهای محاسبات و برای دریافت مقدار بازگشتی یک تابع فراخوانی شده استفاده میشود، در حالی که متغیرهای محلی برای اهداف مشابهی همانند ثباتها استفاده میشوند و همچنین برای انتقال دادن آرگومانهای تابع استفاده میشوند. حداکثر اندازه پشته عملوند و آرایه متغیر محلی، محاسبه شده توسط کامپایلر، بخشی از ویژگی های(attributes) هر تابع است. هر کدام از آنها میتواند بهطور مستقل از ۰ تا ۶۵۵۳۵ مقدار داشته باشد، که هر مقدار ۳۲ بیت است. long
و double
که ۶۴ بیت هستند، دو متغیر محلی متوالی (که نیازی به اینکه به صورت ۶۴ بیت در یک ردیف در آرایه متغیرهای محلی قرار گرفته باشد نیست) یا یک مقدار در پشته عملوند را میگیرند (اما به عنوان دو واحد در عمق پشته بهشمار میرود)
مجموعه دستورالعمل
هر بایت کد از یک بایت که نشانگر آپ کد (به انگلیسی: opcode) است، همراه با صفر یا تعداد بایت بیشتر برای عملوندها تشکیل شدهاست.
از ۲۵۶ بایت-long آپ کد ممکن، تا تاریخ ۲۰۱۵، ۲۰۲ در حال استفاده هستند (~ ۷۹٪)، ۵۱ برای استفاده در آینده رزرو شدهاند(~ ۲۰٪)، و ۳ دستورالعمل (~ ۱٪) بهطور دائمی برای استفاده پیادهسازیهای جی وی ام رزرو شدهاست. دو تا از اینها (impdep2
و impdep1
) به ترتیب مسئول ایجاد تله(trap) برای پیادهسازی خاص نرمافزار و سختافزار هستند. سومی توسط دیباگرها برای پیادهسازی نقطه توقف(break point) استفاده میشود.
دستورالعملها به تعدادی گروه گسترده تقسیم میشوند:
- بارگذاری و ذخیره (مانند
aload_0
،istore
) - ریاضیات و منطق (مانند
ladd
،fcmpl
) - تبدیل نوع (به انگلیسی: Type conversion) (مانند
i2b
،d2i
) - ایجاد و دستکاری شی (به انگلیسی: Operand stack management)(
new
،putfield
) - مدیریت پشته عملوند (مانند
swap
،dup2
) - انتقال کنترل (مانند
ifeq
،goto
) - فراخوانی تابع و بازگشت (مانند
invokespecial,
areturn
)
همچنین چندین دستورالعمل برای تعدادی از کارهای تخصصی تر مانند پرتاپ استثنا (به انگلیسی: exception throwing)، هماهنگ سازی (به انگلیسی: synchronization) و غیره وجود دارد.
بسیاری از دستورالعملها دارای پیشوند و / یا پسوندهای مربوط به انواع عملوندهایی که روی آن عمل میکنند هستند. که به شرح زیر است:
پسوند/پیشوند | نوع عملوند |
---|---|
i
| integer |
l
| long |
s
| short |
b
| byte |
c
| character |
f
| float |
d
| double |
a
| reference |
برای مثال، iadd
دو عدد صحیح(integer) را جمع میکند، در حالی که dadd
دو عدد double را جمع میکند. دستورالعملهای const
، load
و store
میتوانند یک پسوند از فرم _ n
داشته باشند، که n یک عدد از ۰–۳ برای load
و store
میباشد. حداکثر مقدار n برای const
بسته به نوع متفاوت است.
دستورالعمل const
یک مقدار از نوع مشخص شده را بر روی پشته قرار میدهد. به عنوان مثال، iconst_5
یک عدد صحیح (مقدار ۳۲ بیتی) با مقدار ۵ را روی پشته قرار میدهد، در حالی که dconst_1
یک double با مقدار 1 (64bit floating point value) را بر روی پشته قرار میدهد. همچنین دستورالعمل aconst_null
وجود دارد، که یک مرجع(reference) null
را روی پشته قرار میدهد. n برای دستورالعمل load
و store
، شاخص(index) را در آرایه متغیر محلی برای بارگیری یا ذخیره کردن مشخص میکند. دستورالعمل aload_0
شی (به انگلیسی: object) را در متغیر محلی ۰ را بر روی پشته قرار میدهد (این معمولاً شیthis
است). istore_1
عدد صحیح بالای پشته را در متغیر محلی ۱ ذخیره میکند. برای متغیرهای محلی فراتر از ۳، پسوند وجود ندارد و باید از عملوند استفاده شود.
مثال
کد جاوا زیر را در نظر بگیرید:
outer:
for (int i = 2 ; i < 1000; i++) {
for (int j = 2 ; j < i; j++) {
if (i % j == 0)
continue outer;
}
System.out.println (i);
}
یک کامپایلر جاوا ممکن است کد جاوای بالا را به بایت کد به صورت زیر ترجمه کند، فرض بر این است که کد بالا در یک تابع قرار داده شدهاست:
0: iconst_2
1: istore_1
2: iload_1
3: sipush 1000
6: if_icmpge 44
9: iconst_2
10: istore_2
11: iload_2
12: iload_1
13: if_icmpge 31
16 : iload_1
17: iload_2
18: irem
19: ifne 25
22: goto 38
25: iinc 2, 1
28: goto 11
31: getstatic #84; // Field java/lang/System.out:Ljava/io/PrintStream;
34: iload_1
35: invokevirtual #85; // Method java/io/PrintStream.println:(I)V
38: iinc 1, 1
41: goto 2
44: return
نسل
رایجترین زبان که با تولید جاوا بایت کد ماشین مجازی جاوا JVM را هدف قرار دادهاست، جاوا است. در ابتدا تنها یک کامپایلر وجود داشت، کامپایلر javac از Sun Microsystems، که کد منبع جاوا را به جاوا بایت کد کامپایل میکند؛ اما به دلیل اینکه تمام خصوصیات بایت کدی جاوا در حال حاضر در دسترس است، دستههای دیگر کامپایلرهایی را تولید کردهاند که جاوا بایت کد تولید میکنند. نمونههایی از کامپایلرهای دیگر عبارتند از:
- Jikes، از جاوا به جاوا بایت کد کامپایل میکند (توسعه یافته توسط IBM، اجرا شده در C ++)
- Espresso، از جاوا به جاوا بایت کد کامپایل میکند (فقط جاوا ۱٫۰)
- کامپایلر GNU برای جاوا (GCJ)، از جاوا به جاوا بایت کد کامپایل میکند؛ همچنین میتواند به کد ماشین بومی (به انگلیسی: native) کامپایل کند و تا نسخه ۶ بخشی از مجموعه کامپایلر گنو (GCC) بود.
بعضی از پروژهها، اسمبلرهای جاوا را قادر میسازند که به ضورت دستی جاوا بایت کد بنویسند. کد اسمبلی ممکن است توسط ماشین تولید شود، مثلاً توسط یک کامپایلر که یک ماشین مجازی جاوا را هدف قرار میدهد. اسمبلرهای مشهور جاوا عبارتند از:
- Jasmin، توصیفهای متنی برای کلاسهای جاوا میگیرد، که در قالب یک ترکیب اسمبلی-مانند ساده است و از مجموعه دستورالعملهای جی وی ام استفاده کرده و فایل کلاس جاوا(Java class file) تولید میکند
- Jamaica، یک زبان اسمبلی ماکرو برای ماشین مجازی جاوا است. نحو جاوا (Java syntax) برای تعریف کلاس یا رابط(interface) استفاده میشود. بدنه تابع با دستورالعملهای بایت کد مشخص میشوند.
- Krakatau Bytecode Tools، در حال حاضر شامل سه ابزار است: decompiler و disassembler برای فایلهای کلاس جاوا و یک اسمبلر برای ایجاد فایلهای کلاس.
- Lilac، یک اسمبلر و disassembler برای ماشین مجازی جاوا.
دیگران برای زبانهای برنامهنویسی مختلف کامپایلرهایی را که ماشین مجازی جاوا را هدف قرار میدهند، توسعه دادهاند مانند:
- ColdFusion
- JRuby و Jython، دو زبان اسکریپتی بر اساس روبی و پایتون
- Apache Groovy، یک زبان اسکریپتیزبان اسکریپتی مبتنی بر جاوا است
- Scala، یک زبان برنامهنویسی عمومی و نوعی-امن است که از برنامهنویسی شی گرا و کاربردی پشتیبانی میکند
- JGNAT و AppletMagic، از زبان Ada به Java bytecode کامپایل میکند
- C به کامپایلر بایت کد جاوا
- Clojure، یک زبان برنامهنویسی کاربردی، غیرقابل تغییر، عمومی در خانواده Lisp با تأکید قوی بر همزمان سازی
- MIDletPascal
- کد اسکریپت JavaFX به جاوا بایت کد کامپایل میشود
- کوتلین
- کد منبع آبجکت پاسکال با استفاده از کامپایلر Free Pascal 3.0+ به جاوا بایت کدکامپایل میشود.
اجرا
امروزه ماشینهای متعددی وجود دارند که هم رایگان و هم تجاری هستند.
اگر اجرای جاوا بایت کد در یک ماشین مجازی جاوا نامطلوب باشد، یک توسعه دهنده میتواند کد منبع جاوا یا بایت کد را بهطور مستقیم به کد ماشین بومی با ابزارهایی مانند کامپایلر GNU برای جاوا (GCJ) کامپایل کند. بعضی از پردازندهها میتوانند بایت کد جاوا را بهطور بومی اجرا کنند. چنین پردازنده هاییپردازندههای جاوا نامیده میشوند.
پشتیبانی از زبانهای پویا
ماشین مجازی جاوا از زبانهای پویا تایپ شونده (به انگلیسی: dynamically typed languages) پشتیبانی میکند. بیشتر دستورالعملهای موجود در جی وی ام ثابت تایپ شونده (به انگلیسی: statically typed) هستند - به این معنی که فراخوانی توابع امضا(signature) خود را در زمان کامپایل تایپ-چک میکنند، بدون مکانیزمی برای تعویق این تصمیم به زمان اجرا، یا برای انتخاب ارسال تابع با یک روش جایگزین.
JSR 292 (از زبانهای پویا تایپ شونده در بسترهای جاوا پشتیبانی میکند) دستورالعمل جدیدinvokedynamic
را در سطح جی وی ام اضافه کرد، تا فراخوانی تابع به داینامیک تایپ-چک (به انگلیسی: type checking) تکیه کند (به جای استاتیک تایپ-چک موجود با دستورالعملinvokevirtual
). داوینچی ماشین (به انگلیسی: Da Vinci Machine) یک نمونه اولیه ماشین مجازی است که میزبان توسعه دهندههای جی وی ام با هدف پشتیبانی از زبانهای پویا است. همهٔ جی وی امهایی که از ۷ JSE پشتیبانی میکنند شامل آپ کد invokedynamic
هستند.
جستارهای وابسته
- Java bytecode instruction listings
- Java class file
- List of JVM languages
- Java backporting tools
- C to Java Virtual Machine compilers
- JStik
- Common Intermediate Language (CIL), Microsoft's rival to Java bytecode
- ObjectWeb ASM
- Byte Code Engineering Library
منابع
1.فهم بایت کد شما را به برنامهنویس بهتری تبدیل میکند
2.The Java Virtual Machine Specification
3.Jamica: The Java virtual JVM macro assembler