අපි මුලින්ම සරලව තේරුම් ගමු Java code එකක් සහ C code එකක් execute වෙන්නේ කොහොමද කියලා.

සරලව පැහැදිලි කරනවා නම් අපි ලියන Java code file එකක් Java byte code file එකක් බවට පත් කරලා ඒක .class file එකක store කරනවා එතකොට මේ .class file එකේ තියෙන byte code කියවන්න පුළුවන් Java Virtual Machine එකට. එතකොට Java Virtual Machine එක තමා byte code, native code බවට (On the fly compilation) පත්කරමින් Operating System එකේ තියෙන Kernel (Hardware එක්ක ගනුදෙනු කරන program එක) API එක්ක ගනුදෙනු කරමින් execution එක කරන්නේ.

මේ byte code machine code කරන ක්‍රම දෙකක් තියෙනවා

1 Interpret කරන එක එකියන්නේ line by line පේලියෙන් පේලිය
2 JIT (Just in time) මේකෙදි වෙන්නේ කොටස් කොටස් වශයෙන්

එතකොට C වලින් ලියන code එකකදී වෙන්නේ කෙලින්ම compiler එක native code එකට පත් කරලා ඒක executable file එකක් විදිහට store කරනවා (ඇත්ත කතාව මෙච්චර සරල නහ, තේරුම් ගන්න ඕන නිසා මෙහෙම හිතාගන්න)
එතකොට මෙතැනදී අර Java වලදී වගේ අතර මැද Virtual machine එකක් නැහැ, ඒවගේම මේක Virtual Machine එකක් හරහා execute වෙනවාට වඩා Memory, CPU resources අඩුවෙන් පාවිච්චි කරලා ඉතා වේගයෙන් execute වෙනවා.
එහෙනම් මොකටද virtual machine එකක් දාගෙන දඟලන්නේ කෙලින්ම execute කරන්න පුළුවන් නේ?
ඒකට උත්තරේ ලබාගන්න අපි CPU architecture designs සහ CPU architectures ගැන සරල අවබෝදයක් ලබාගමු.

CPU architecture designs සහ CPU architectures

ප්‍රධාන CPU architecture designs දෙකක් තියෙනවා

1 Complex instruction set computer  (CISC)
2  Reduced instruction set computer (RISC)

අපි මේ පිලිබඳ ඉතාමත් සරල අවබෝදයක් ලබාගමු ලිපියේ ඉතිරි කොටස තේරුම් ගන්න.

Complex Instruction set computer එකකට පුළුවන් instruction set එකක්ම memory ගෙන්නාගෙන multi step operations එකවර කරලා දාන්න. එයාට instruction set ගෙනල්ල තියාගන්න වේනම් unit එකක් තියෙනවා, එනිසා execution එකේදී  hardware විශාල කාර්යක් කරනවා.

Reduced  Instruction set computer එකේදී එක instruction එකක් complete කරන්න CPU cycles වැඩි ප්‍රමාණයක් අවශ්‍ය වෙනවා. ඒවගේම මේවා සම්පූර්ණ කරගන්න මෙයාට යම් කිසි කාලයක් අවශ්‍ය වෙනවා, DRAM වලට යනකොට මෙයාට තව වැඩ වැඩිවෙනවා මොකද සැරින් සැරේ RAM එක charge කරන වැඩෙත් කරන්න ඕන. මෙයා execution එකේදී software මත depend වෙනවා මොකද මෙයාට කියලා දෙන්න ඕන කරන්න ඕන දේවල් එකින් එක.

මේ දෙක සරලව තේරුම් ගන්න පුළුවන් අන්තිම අවස්ථාවට එමු, හිතන්න 2 + 3 එකතු කරන්න තියෙනවා කියලා CISC ට පුළුවන් ඕක සම්පූර්ණයෙන් අරගෙන උත්තරේ memory එකට එවන්න, නමුත් RISC එකට ඉස්සෙල්ලම 2 යවන්න ඕන ඊට පස්සේ + යවන්න ඕන ඊටපස්සේ 3 යවන්න ඕන. (ඇත්ත කතාව මේක නෙවෙයි නමුත් සරලව තේරුම්ගන්න මෙහෙම හිතන්න)

දැන් අපි බලමු මේ CPU designs දෙක භාවිත වෙන processor architectures මොනවද කියලා

CISC architecture එකේ processor බාවිතා වෙන්නේ Desktop / Server machine වල, ඒවගේම විදුලියත් වැඩිපුර භාවිතා කරනවා මොකද එකවර විශාල වැඩකොටසක් කරන නිස. සාමන්යෙන් අවම 40 watt වත් විදුලි බලයක් පාවිච්චි කරන බලගතු processor තමා තියෙන්නේ. CISC වලට උදාහරණ අපේ මේස උඩ තියෙන computer වල තියෙන amd64(64bit),  i386(32 bit).

RISC වලට උදාහරණ අපි හැමෝගෙම phone වල තියෙන ARM architecture එක. විදුලිය watt එකකටත් වඩා අඩු ප්‍රමාණයක් බාවිත කරන තැන්වල වගේම අරමුණට අනුව powerful supercomputers වලත් මේවා පාවිච්චි කරනවා. (තේරුම් ගැනීමට අවශ්‍ය නිසා low-end devices වල පාවිච්චිකරන එක ගැන හිතන්න)(Phones, Tablets, CCTV DVR)

දැන් තේරුම් ගන්න ඕන දේ තමා CISC එකට compile කරපු C program එකක් RISC එකේ run කරන්න බැහැ, සරලව කිව්වොත් computer එකේ run වෙන software එක phone එකට දැම්මොත් run වෙන්නේ නැහැ.

ඇයි…?

Computer එක CISC architecture එකේ එයා එකපාර instruction සෙට් එකක්ම අරගෙන වැඩේ කරනවා, එයාට ලොකු විදුලි බලයක් තියෙනවා, නමුත් phone එක RISC architecture එකේ මෙයාට එකින් එක කියල දෙන්න ඕන මෙයාට ලොකු power එකක් නැහැ.

සරලව කිව්වොත් CISC එකට කියන්න ඕන විදිහට නෙවෙයි RISC එකට කියන්න ඕන. එනිසා CISC executable එකක තියෙන binary instructions. RISC processor එකකට තේරුමක් නැතිව යනවා. මේකට අපිට cross compiler එකක් පාවිච්ච් කරලා amd64 එකේ වැඩකරන software එක armel වල වැඩකරන්න cross compile කරන්න පුළුවන්. මං අත්දැකීමෙන් දැකල තියෙනවා cross compile කරමා executable එකේ size එක ලොකු වෙනවා, මොකද binary instruction යවන්න ඕන විදිහ එකින් එක තියාගන්න ඕන (මං කලින් කිව්වා මෙයාගේ execution process එකේ ගොඩක් දේවල් software වල depend වෙනවා කියලා)

දැන් අපි එමු අපේ පලවෙනි ප්‍රශ්නෙට කෙලින්ම execute කරන්න පුළුවන් කම තියෙද්දී ඇයි Virtual Machine එකක්,
උදාහනයකට අපි JAVA Virtual machine එක ගමු JVM එක ලෝකේ තියෙන එක එක processor architecture වලට වැඩ කරන්න හදන එක JVM දියුණු කරන කට්ටියගේ වැඩක්, application එක පාවිච්චි කරන කෙනා processor architecture ගැනවත් cross compiler ගැනවත් දුක්වෙන්නවත් ඒක ගැන ඉගෙනගන්න මහන්සිවෙන්නවත් අවශ්‍ය නැහැ  එයාට තියෙන්නේ අදාළ application එක jvm එක බාවිතයෙන් run කරන්න විතරයි JVM එක operating system එකත් එක්ක බලාගයි application එක කොහොමද execute කරන්නේ කියල.
ඒවගේම හිතන්න අවුරදු 10 ක ලොකු project එකක් කරාට පස්සේ system එකේ processor එකක් මාරු කරන්න උනොත්? අන්න එවෙලාවට virtual machine එකක් මගින් execute වෙනවා නම් ලොවෙත් නැහැ. (virtual machine වර්චස් machine වෙන අවස්ථා නැතුවම නැහැ 😀 😀 resources මරනවනේ, programmer ගේ අතේ සෑහෙන්න වැඩකොටසක් තියෙනවා resources අඩුවෙන්ම කන විදිහට වග බලාගන්න)

Android, Dalvic Virtual Machine Linux

Android Run වෙන්නේ Linux මත android වලත් JVM එකට සමාන Virtual Machine එකක් දාල තියෙනවා Dalvic VM කියලා Linux උඩට. අපි android App එකක් හැදුවම ඒක SDK එකෙන් Java byte code එකට පත් කරලා එක Dex Compiler එකෙන් Dalvic Byte code බවට පත්කරලා තමා apk file ඇතුලේ store කරන්නේ. Android 4.4 වෙනකම් Android app JIT විදිහට Dalvic VM තමා execute කරේ. ඉතින් මේකට සැහෙන්න resources ඕන උනා පොඩි RAM තියෙන phone වල පාවිච්චි කරන්න ටිකක් අමාරු උනා. නමුත් 5.0 එක්ක Android Run Time environment  එක සමග Ahead Of Time compilation හඳුන්වලා දුන්නා එකේදී Android App වල තියෙන Dalvic Byte code, App එක install කරන වෙලාවේම Dalvic VM එක බාවිත කරලා Native code බවට පත් කරලා device එකේ .oat file එකක් විදිහට store කරලා ඒක බාවිතා කිරීම නිසා Android App වේගයෙන් execute වුනා නමුත් install වෙන්න වැඩි වෙලාවක් ගත උනා, නමුත් android 7.0 එක්ක ART සඳහා JIT හඳුන්වලා දුන්නා එකෙන් install වෙන්න ගතවෙන කාලය අඩු උනා.

එතකොට android app dalvic byte code වලින් තියෙන්න හේතුව Android තියෙන්නේ limited devices කිහිපයකට නෙවෙයි devices ගොඩක් තියෙනවා processor architectures ගොඩක් තියෙනවා, එහෙම නැතුව කෙලින්ම compile කරන්න ගියානම් Application Developer ඔය තියෙන හැම architecture එකකටම වෙන වෙනම compile කරන්න වෙනවා, ඒක අසාර්ථක අසීරු තේරුමක් නැති වැඩක්.

මම Shuja Rafi