جاوا بایت کد

از ویکی‌پدیا، دانشنامهٔ آزاد

جاوا بایت کد (به انگلیسی: Java bytecode) مجموعه دستورالعمل‌های ماشین مجازی جاوا یا به اختصار JVM است.

ارتباط با جاوا[ویرایش]

یک برنامه‌نویس جاوا نیازی به دانستن یا درک جاوا بایت کد ندارد. با این حال، همان‌طور که در مجله IBM developerWorks پیشنهاد شده‌است، «درک بایت کد و آنچه که توسط کامپایلر جاوا تولید می‌شود، به برنامه نویس جاوا کمک می‌کند همانطور که دانش اسمبلی(Assembly) به برنامه نویس C یا C ++ کمک می‌کند.»

مجموعه دستورالعمل معماری[ویرایش]

جی وی ام(JVM) هم یک ماشین پشته ای (به انگلیسی: stack machine) و هم یک ماشین ثبات (به انگلیسی: register machine) است. هر فریم برای یک فراخوانی تابع دارای یک "پشته عملوند" و یک آرایه از "متغیرهای محلی" است. : 2.6  پشته عملوند برای عملوندهای محاسبات و برای دریافت مقدار بازگشتی یک تابع فراخوانی شده استفاده می‌شود، در حالی که متغیرهای محلی برای اهداف مشابهی همانند ثبات‌ها استفاده می‌شوند و همچنین برای انتقال دادن آرگومان‌های تابع استفاده می‌شوند. حداکثر اندازه پشته عملوند و آرایه متغیر محلی، محاسبه شده توسط کامپایلر، بخشی از ویژگی های(attributes) هر تابع است. : 4.7.3  هر کدام از آنها می‌تواند به‌طور مستقل از ۰ تا ۶۵۵۳۵ مقدار داشته باشد، که هر مقدار ۳۲ بیت است. long و doubleکه ۶۴ بیت هستند، دو متغیر محلی متوالی : 2.6.1  (که نیازی به اینکه به صورت ۶۴ بیت در یک ردیف در آرایه متغیرهای محلی قرار گرفته باشد نیست) یا یک مقدار در پشته عملوند را می‌گیرند (اما به عنوان دو واحد در عمق پشته به‌شمار می‌رود) : 2.6.2 

مجموعه دستورالعمل[ویرایش]

هر بایت کد از یک بایت که نشانگر آپ کد (به انگلیسی: opcode) است، همراه با صفر یا تعداد بایت بیشتر برای عملوندها تشکیل شده‌است. : 2.11 

از ۲۵۶ بایت-long آپ کد ممکن، تا تاریخ ۲۰۱۵، ۲۰۲ در حال استفاده هستند (~ ۷۹٪)، ۵۱ برای استفاده در آینده رزرو شده‌اند(~ ۲۰٪)، و ۳ دستورالعمل (~ ۱٪) به‌طور دائمی برای استفاده پیاده‌سازی‌های جی وی ام رزرو شده‌است. : 6.2  دو تا از اینها (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) و غیره وجود دارد.

بسیاری از دستورالعمل‌ها دارای پیشوند و / یا پسوندهای مربوط به انواع عملوندهایی که روی آن عمل می‌کنند هستند. : 2.11.1  که به شرح زیر است:

پسوند/پیشوند نوع عملوند
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 برای ماشین مجازی جاوا.

دیگران برای زبان‌های برنامه‌نویسی مختلف کامپایلرهایی را که ماشین مجازی جاوا را هدف قرار می‌دهند، توسعه داده‌اند مانند:

اجرا[ویرایش]

امروزه ماشین‌های متعددی وجود دارند که هم رایگان و هم تجاری هستند.

اگر اجرای جاوا بایت کد در یک ماشین مجازی جاوا نامطلوب باشد، یک توسعه دهنده می‌تواند کد منبع جاوا یا بایت کد را به‌طور مستقیم به کد ماشین بومی با ابزارهایی مانند کامپایلر GNU برای جاوا (GCJ) کامپایل کند. بعضی از پردازنده‌ها می‌توانند بایت کد جاوا را به‌طور بومی اجرا کنند. چنین پردازنده هاییپردازنده‌های جاوا نامیده می‌شوند.

پشتیبانی از زبان‌های پویا[ویرایش]

ماشین مجازی جاوا از زبان‌های پویا تایپ شونده (به انگلیسی: dynamically typed languages) پشتیبانی می‌کند. بیشتر دستورالعمل‌های موجود در جی وی ام ثابت تایپ شونده (به انگلیسی: statically typed) هستند - به این معنی که فراخوانی توابع امضا(signature) خود را در زمان کامپایل تایپ-چک می‌کنند، بدون مکانیزمی برای تعویق این تصمیم به زمان اجرا، یا برای انتخاب ارسال تابع با یک روش جایگزین.

JSR 292 (از زبان‌های پویا تایپ شونده در بسترهای جاوا پشتیبانی می‌کند) دستورالعمل جدیدinvokedynamic را در سطح جی وی ام اضافه کرد، تا فراخوانی تابع به داینامیک تایپ-چک (به انگلیسی: type checking) تکیه کند (به جای استاتیک تایپ-چک موجود با دستورالعملinvokevirtual). داوینچی ماشین (به انگلیسی: Da Vinci Machine) یک نمونه اولیه ماشین مجازی است که میزبان توسعه دهنده‌های جی وی ام با هدف پشتیبانی از زبانهای پویا است. همهٔ جی وی ام‌هایی که از ۷ JSE پشتیبانی می‌کنند شامل آپ کد invokedynamic هستند.

جستارهای وابسته[ویرایش]

منابع[ویرایش]

1.فهم بایت کد شما را به برنامه‌نویس بهتری تبدیل می‌کند

2.The Java Virtual Machine Specification

3.Jamica: The Java virtual JVM macro assembler

4.Krakatau home page

5.Free Pascal 3.0 release notes

6.Free Pascal JVM Target

7.see JSR ۲۹۲

پیوند به بیرون[ویرایش]