jeni duke lexuar...
Leksione, Literature, Raste Studimi

Përse Android përdor Dalvik dhe jo Sun JVM?

Për ekzekutimin e programeve Java, në sistemin Android, përdoret “Dalvik Virtual Machine”, i cili ndryshon shumë nga një makinë standarde siç është p.sh. Sun JVM. Në rreshtat e mëposhtëm do të përqendrohemi eksluzivisht në dallimet e arkitekturës se përdorur nga këto dy “Java Virtual Machines (JVM)”.

Gjuha e programimit Java lindi si nevojë për të krijuar software të aplikueshëm në ambiente heterogjene rrjetash kompjuterike. Në këta ambiente, aplikacionet do te duhet të ekzekutohen në arkitektura hardware dhe software shumë të ndryshme. Për të mundësuar ketë, Java duhet të jetë “architecture neutral”, pra e pavarur prej arkitekturës ku një program java ekzekutohet.

Për të mundësuar këtë “neutral architecture concept”, platforma java përdor një gjuhë të ndërmjetme të quajtur “java bytecode”, e cila është e njëjtë pavarësisht se çfarë hardware, ISA (Instruction Set Architecture), apo sistemi operativ përdoret për ekzekutimin e programeve java. Kështu, nëpërmjet kompilatorit, programi në java, shndërrohet në instruksione të tipit “java bytecode”, të organizuar në skedarë binarë të formës  .class, të quajtur “java class files”. Për të lehtësuar përdorimin e programeve java,  të gjitha “java class files” të një programi, paketohen (mblidhen) bashkë në një skedar të vetëm binar të tipit .jar, ose “java archive”.

Pas kësaj, nuk mbetet gjë tjetër veçse të mundësohet ekzekutimi, në një platformë të caktuar, i programeve të përbërë nga “java bytecode”, që janë tashmë në format binar .jar. Për këtë, përdoret “Java Virtual Machine” shkurt JVM. JVM është një  « process virtual machine », pra një makinë abstrakte ekzekutimi instruksionesh (software interpreter), e cila bën të mundur që “java bytecode” të ekzekutohen në një platformë hardware/software të caktuar. Kështu, duke perdorur JVM për platforma të ndryshme, do të bëhej e mundur interpretimi i të njëjtit program binar java në Linux, Windows, Mac, Solaris etj. Në këtë mënyrë shndërohet pra në realitet slogani i Sun Java : “Write once, run anywhere” (shkruaj një herë, ekzekuto kudo).

Ky proces tregohet skematikisht në figurën e mëposhtëme.

dalvik fig 1

Pavarësisht se programet java, nëpërmjet “java  bytecode”, mund te ekzekutohen te pandryshuar ne platforma te ndryshme, vetë kodi i JVM, meqenëse ai bazohet mbi një sistem të caktuar operativ, është i ndryshëm për platforma të ndryshme software. Në fund të  shkrimit gjendet shembulli i nje “Virtual Machine” shkruar ne C.

Vendi që zë JVM në arkitekturën e një kompjuteri, tregohet skematikisht më poshtë.

JVM ne nje computer platform

Dy fjalë për “java bytecode”:

Natyrshëm lind pyetja : përse përdoret “java bytecode” si një abstraksion i ndërmjetëm që siguron “ABI compatibility” ? (ABI = Application Binary Interface).

Përgjigja është e thjeshtë : “java bytecode” janë instruksione shumë më primitivë se vetë Java, duke e bërë kështu më të lehtë implementimin e tyre nëpërmjet JVM.

Kështu, kodi operativ (“opcode”) i “java bytcode”  është vetëm 1 byte i gjatë.

Vetëm 205 instruksione prej 256 kodet e mundshëm janë shfrytëzuar. 51 prej tyre janë RFU (Reserved For Future Use).

Ne tabelën e mëposhtëme (marre prej Patterson/Hennessy, COD-The hardware/software Interface) tregohen instruksionet kryesorë të java bytecode.

dalvik tabela e java bytecodes

Në tabelë vihet re se instruksionet arithmetike nuk specifikojnë operanda, duke bërë që arkitektura e makinës që ekzekuton “java bytecode” të jetë një “zero operand”, e quajtur ndryshe edhe si “stack machine”. Për më shumë rreth “stack machine” mund te lexoni ketu: “Makina me zero operandë“.

Arsyet që kanë shtyrë konceptuesit e gjuhës Java të zgjedhin një arkitekturë të tipit “stack machine”, duhen kërkuar në objektivat e konceptimit (“design goals”), që ata vendosën në fillesat e kësaj gjuhe. Kështu, Java lindi si pjesë e një projekti kërkimor me qëllim zhvillimin e programeve të avancuar të aplikueshëm në pajisje rrjetash (“network devices”) dhe sistemesh të imbarkuar ( “embedded systems”). Për pasojë, objektivat që u fiksuan për gjuhen java ishin që ajo të ishte “small, reliable, portable, distributed, real-time operating platform”.

Kështu, për të thjeshtuar kompilimin, duhej që, së pari, të hiqej dorë prej regjistrave ku vendosen operandat, por veprimet të bazoheheshin mbi “stack”. Së dyti, për të bërë te mundur që kodi binar të mund të integrohej në pajisje gjithfarë, ku madhësia e kujtesës është problematike, do të duhej që madhesia e kodit të ishte mundësisht sa më e vogël. Këtë karakteristikë mund ta siguronte një bashkësi instruksionesh, e cila operandat i kërkon në stack, pra një “stack machine”.

Si qëndron çeshtja e Java Virtual Machine në rastin e Android ?

Android eshte nje “complete software stack”, i cili përfshin “Linux kernel”, “system libraries”, “application framework” si dhe disa aplikime te dobishem. Skematikisht kjo tregohet ne figuren e meposhtme.

Komponenti qe mundeson ekzekutimin e programve Java quhet “Android runtime”, i cili perbehet prej “Dalvik Virtual Machine dhe “Java core libraries”.

dalvik fig androidPra, Android nuk përdor një JVM standard siç është p.sh. Sun (Oracle) JVM, por përdor Dalvik VM, i cili është shumë i ndryshëm nga një JVM standard.

Një nga dallimet thelbësore që dallojnë Dalvik nga Sun JVM, është arkitektura. Kështu, « java bytecode », siç trajtuam me lart, funksionojnë sipas arkitekturës  « stack machine ». Dalvik VM opcodes janë te ndryshëm nga « java opcode » standard, pasi kërkojnë një « register-based machine » për tu ekzekutuar.

Le të shikojmë disa nga kriteret kryesore, që konceptuesit e Dalvik kanë marrë në konsideratë, të cilat kanë influencuar zgjedhjen e tyre.

Kështu, sipas Dan Bornstein, konceptuesit te Dalvik VM, ai duhet të ishte një makinë virtuale që do të punonte në kushtet kur sistemi do të kishte:

–      Procesor me shpejtësi të ulët.

–      Relativisht pak kujtesë operative (dhjetëra/qindra MB).

–      Sistem operativ (Android), i cili nuk përdor “swap space”.

–      Dhe me kryesorja, punon i ushqyer me bateri.

Dy faktorët e parë kanë evoluar me kalimin e kohës, ndërsa kursimi i energjisë të përdorur mbetet faktori i pandryshuar dhe për rrjedhojë edhe vendimtar në përcaktimin e arkitekturës « register-based machine » të përdorur prej Dalvik. Kështu, kjo arkitekturë rezulton të sigurojë këto avantazhe, krahasuar me “stack machine”:

–      Eliminon “instruction dispatch”. “Instruction dispatch” është faza, e cila pas dekodimit të instruksionit, rezervon  pjesë  te CPU (“execution units”) që do të angazhohen në ekzekutimin e instruksionit.

–      Eliminon aksesin e panevojshëm në kujtesë. Vërtet, një “register-based machine”, krahasuar me një “stack machine”, i ripërdor në mënyrë shumë më efektive variablat që gjenden në regjistra.

–      Shfrytëzon më mirë “instruction stream”, pasi siguron instruksione me densitet të lartë semantik.

Statistikisht rezulton se Dalvik VM, në krahasim me një JVM standard të  ketë:

–      30 % më pak instruksione.

–      35 % më pak kode operative.

–      35 % Byte më shumë në “instruksion stream” ( “opcode” në Dalvik është 2 byte, ndërsa një JVM “opcode” është 1 byte).

Përderisa Dalvik, për kapjen e operandave, përdor regjistra virtualë, duhet që edhe instruksionet e tij ta mundësojnë këtë. Kështu “Dalvik bytecodes” nuk janë më 1 byte si në rastin e “java bytecode”, por 2 byte.  Një konvertues i posaçëm, i quajtur dx, përdoret për te konvertuar java .class files ne format  .dex (“Dalvik executable”), ashtu siç tregohet ne figurën e mëposhtme.

Dalvik dex format

 

Cila është  e ardhmja e përdorimit të Dalvik?

Në Android 4.4 KitKat (tetor 2013) u shfaq për herë të parë publikisht ART (Android Runtime), i cili është  një ambient ekzekutimi (“runtime environment”) i programve Java, alternativë e Dalvik. Që prej Android 5.0 Lollipop (nëntor 2014), Dalvik është zevendësuar plotësisht prej ART-së.

Cili është ndryshimi thelbësor ndërjmet Dalvik dhe ART ?

Dalvik është një JIT, ose Just In Time compiler : gjatë ekzekutimit të aplikacionit, Java bytecodes interpretohen aty-për-aty prej Dalvik duke i konvertuar ato në instruksione native (instruksione të ekzekutueshme direkt prej procesorit; p.sh. ARM architecture).

ART është një AOT, ose Ahead On Time compiler : në momentin e instalimit të aplikacionit, Java bytecodes kompilohen paraprakisht, duke i konvertuar ato në instruksione native (ARM).

Për të siguruar “backward compatibility” ART përdor të njëjtët “input bytecodes” si edhe Dalvik (Dalvik bytecodes). Shikoni figurën e mëposhtëme për më shumë detaje.

 

art_view

Natyrisht që, duke përdorur dy mënyra krejt të ndyshme kompilimit, Dalvik dhe ART shfaqin karakteristika të ndryshme. ART suguron disa përparësi krahasuar me Dalvik, ashtu siç tregohet në mënyrë të përmbledhur në tabelën e mëposhtëme.

 

Karakteristika

Dalvik

ART

Metoda e kompilimit JIT AOT
Storage space footprint Më e vogël Më e madhe
App. load time Më e gjatë Më e shkurtër
CPU usage Më e madhe Më e vogël
Battery life Më e vogël Më e madhe
App. runtime Më ngadalë Më shpejt
App. installation time Më e shkurtër Më  e gjatë

 

 

Referenca :

1. The Java Language Environment, James Gosling, Henry McGilton- Sun Microsystems, May 1996.

2. Virtual Machine Showdown: Stack Versus Registers, Yunhe Shi, etj.

3. Dalvik VM Internals, Dan Bornstein, Google

4. Android Dalvik reference

—–

Shembull i realizimit të një “register-based VM “.

/*
 * myvm.c
 */
#include <stdio.h>
#define NUM_REGS 4
#define TRUE    1
#define FALSE   0
#define INVALID -1
enum opCodes {
    HALT  = 0x0,
    LOAD  = 0x1,
    ADD   = 0x2,
};
/*
 * Register set of the VM
 */
int regs[NUM_REGS];
/*
 * VM specific data for an instruction
 */
struct VMData_ {
  int reg0;
  int reg1;
  int reg2;
  int reg3;
  int op;
  int scal;
};
typedef struct VMData_ VMData;
int  fetch();
void decode(int instruction, VMData *data);
void execute(VMData *data);
void run();
/*
 * Addressing Modes:
 * – Registers used as r0, r1,..rn.
 * – Scalar/ Constant (immediate) values represented as #123
 * – Memory addresses begin with @4556
 */
/*
 * Instruction set:
 * – Load an immediate number (a constant) into a register
 * – Perform an arithmetic sum of two registers (in effect,
 *   adding two numbers)
 * – Halt the machine
 *
 * LOAD reg0 #100
 * LOAD reg1 #200
 * ADD reg2 reg1 reg0  // ‘reg2’ is destination register
 * HALT
 */
/*
 * Instruction codes:
 * Since we have very small number of instructions, we can have
 * instructions that have following structure:
 * – 16-bit instructions
 *
 * Operands get 8-bits, so range of number supported by our VM
 * will be 0-255.
 * The operands gets place from LSB bit position
 * |7|6|5|4|3|2|1|0|
 *
 * Register number can we encoded in 4-bits
 * |11|10|9|8|
 *
 * Rest 4-bits will be used by opcode encoding.
 * |15|14|13|12|
 *
 * So an “LOAD reg0 #20” instruction would assume following encoding:
 * <0001> <0000> <00010100>
 * or 0x1014 is the hex representation of given instruction.
 */
 /*
  * Sample program with an instruction set
  */
unsigned int code[] = {0x1014,
                       0x110A,
                       0x2201,
                       0x0000};
/*
 * Instruction cycle: Fetch, Decode, Execute
 */
/*
 * Current state of machine: It’s a binary true/false
 */
int running = TRUE;
/*
 * Fetch
 */
int fetch()
{
  /*
   * Program Counter
   */
  static int pc = 0;
  if (pc == NUM_REGS)
    return INVALID;
  return code[pc++];
}
void decode(int instr, VMData *t)
{
  t->op   = (instr & 0xF000) >> 12;
  t->reg1 = (instr & 0x0F00) >> 8;
  t->reg2 = (instr & 0x00F0) >> 4;
  t->reg3 = (instr & 0x000F);
  t->scal = (instr & 0x00FF);
}
void execute(VMData *t)
{
  switch(t->op) {
    case 1:
      /* LOAD */
      printf(“\nLOAD REG%d %d\n”, t->reg1, t->scal);
      regs[t->reg1] = t->scal;
      break;
    case 2:
      /* ADD */
      printf(“\nADD %d %d\n”, regs[t->reg2], regs[t->reg3]);
      regs[t->reg1] = regs[t->reg2] + regs[t->reg3];
      printf(“\nResult: %d\n”, regs[t->reg1]);
      break;
    case 0:
    default:
      /* Halt the machine */
      printf(“\nHalt!\n”);
      running = FALSE;
      break;
    }
}
void run()
{
  int instr;
  VMData t;
  while(running)
  {
    instr = fetch();
    if (INVALID == instr)
      break;
    decode(instr, &t);
    execute(&t);
  }
}
int main()
{
  run();
  return 0;
}

Diskutim

2 mendime mbi “Përse Android përdor Dalvik dhe jo Sun JVM?

  1. Faleminderit per nje artikull te shkruar vertete bukur dhe qarte. Interesant fakti qe Dalvik perdorka skedaret .class si input. Teorikisht, nje aplikacion i kompiluar ne Java, mund te ekzekutohet ne Android! Kuptohet qe APi nuk jane gjithmone kompatibel, por interesante gjithesesi.

    Postuar nga Andi Mullaraj | 11 Janar 2017, 06:29
  2. Dalvik e perfundoi ciklin e tij tani , Android tjeter do te jete me ART(android runtime) qe ndryshe nga Dalvik qe eshte Just-In-Time compiler ART eshte Ahead-Of-Time compiler pra sdo kemi me bytecode , google premton pergjysmin te kohes se egzkutimit te aplikacionve por me 10-20% kosto me shume ne Mass storage

    Postuar nga Eneas Koto | 20 Qershor 2014, 14:00

Lini një Përgjigje

Ju lutemi, bëni hyrjen me një nga këto metoda që të postoni komentin tuaj:

Stema e WordPress.com-it

Po komentoni duke përdorur llogarinë tuaj WordPress.com. Dilni /  Ndryshoje )

Foto Google

Po komentoni duke përdorur llogarinë tuaj Google. Dilni /  Ndryshoje )

Foto Twitter-i

Po komentoni duke përdorur llogarinë tuaj Twitter. Dilni /  Ndryshoje )

Foto Facebook-u

Po komentoni duke përdorur llogarinë tuaj Facebook. Dilni /  Ndryshoje )

Po lidhet me %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Regjistroni adresën tuaj e-mail për të marrë artikujt e rinj nëpërmjet mesazheve ...

Kategori

Intel CPU Architectures

Procesore Apple Ax

Apple A12 Bionic
Këtë e pëlqejnë %d blogues: