Kasutaja:Pavel Kornyshev/Baitkood

Allikas: Vikipeedia

Baitkood (ingl bytecode, mõnikord ka p-kood, p-kood kaasaskantavast koodist) on standardne vaheesitlus, millesse arvutiprogrammi saab automaatselt edastada. Võrreldes lähtekoodiga, mida on inimesel mugav kirjutada ja lugeda, baitkood on kompaktne esitamine juba eelnevalt (semantiliselt) analüüsitud programmist. Selles on kodeeritud nähtavuspiirkondi ja muid konstruktsioone. Tehnilisest vaatenurgast on baitkood madala taseme masinast sõltumatu kood, mis on koostaja poolt lähtekoodist genereeritud.

Paljud praegusaegsed programmeerimiskeeled, eriti tõlgendatud, kasutavad baitkoodi interpreedi(tõlke) töö hõlbustamiseks ja kiirendamiseks. Baitkoodi tõlge on meetod, mille efektiivsus asub tõlgendamise ja masinakoodiks kompileerimise vahel.

Vormi järgi on baitkood sarnane masinakoodiga, kuid see on mõeldud täitmiseks mitte reaalse protsessori, vaid virtuaalse masina poolt. Tavaliselt vastava programmeerimiskeele tõlk (mõnikord täiendab seda JIT- või AOT-kompilaatoriga) toimib virtuaalse masina kujul. Baitkoodi ja seda teostavate virtuaalsete masinate spetsifikatsioonid võivad keeltes kõvasti erineda: sageli baitkood koosneb juhendist virnastatava virtuaalse masina jaoks[1][2], kuid saadakse kasutada ka registreerimismasinaid[1]. Ikkagi, enamik baitkoodide juhendiseid on tavaliselt võrdsed ühe või mitme assembleri käskudega.

Baitkoodi nimetatakse nii, sest iga opkoodi pikkus on traditsiooniliselt võrdne ühe baidiga. Iga käsk on tavaliselt ühe-baidise opkood (0 kuni 255), millele saavad järgneda mitmesugused parameetrid, näiteks registrinumber või mäluaadress.


Täitmine[muuda | muuda lähteteksti]

Tavaliselt baitkoodi programmi täidab baitkoodi interpretaator. Baidikoodi eelis on suurem efektiivsus ja teisaldatavus, st sama baitkoodi on võimalik kasutada erinevatel platvormidel ja arhitektuuridel, mille jaoks interpretaator on rakendatud. Otseselt interpreteerivad keeled pakuvad samasugust eelist, kuid tavaliselt on baitkood vähem abstraktne ja kompaktsem kui lähtekood. Baitkoodi interpreteerimise tõhusus on tavaliselt kõrgem kui lähtekoodi või abstraktne interpretatsiooni tõlgenduse puhas interpreteerimine. Lisaks on baitkoodi interpretaator sageli lihtsam kui lähtekoodi interpretaator ja seda on lihtsam teisele riistvaraplatvormile üle kanda.

Kõrgtehnoloogilistes virtuaalmasinate rakendustes saab kasutada interpretaatori ja JIT-kompilaatori kombinatsiooni, mis programmitöö käigus tõlgib sageli kasutatavaid baitkoodi fragmente masinakoodiks, rakendades erinevaid optimiseerimismeetodeid. JIT-i kompileerimise asemel võib enne täitmist kasutada AOT-kompilaatorit, tõlkides baitkoodi masinakoodiks.

Samal ajal on võimalik luua protsessoreid, mille jaoks antud baitkood on otse masinakood (sellised eksperimentaalsed protsessorid loodi näiteks Java ja Forth keelte jaoks).

Ajalugu[muuda | muuda lähteteksti]

Esimesed süsteemid, mis kasutasid baitkoodi, olid BCPL-i O-kood (1960ndad), Smalltalk (1976)[3], SIL (Süsteemi rakendamise keel) Snobol-4 jaoks (1967), p-kood (p-kood, 1970, koos Niklaus Wirthiga), Pascal programmeerimiskeele kaasaskantavatele kompilaatoritele[4][5][6].

P-koodi variante kasutati laialdaselt Pascali keele mitmesugustes rakendustes, näiteks UCSD p-süsteemis (UCSD Pascal).[7]

Rakendus[muuda | muuda lähteteksti]

Baitkoodi interpreteeritud keeled on Perl, PHP (näiteks Zend Engine), Ruby (alates versioonist 1.9), Python, Erlang ja paljud teised.

Baitkoodi kasutavad laialdased platvormid[8]:

  • Java baitkood (stack virtuaalne masin), mida teostavad erinevad Java virtuaalmasinad[9][10]. Platvorm oli loodud Sun poolt Java keelele, kuid seda kasutati ka teistes keeltes. On olemas kümneid suure jõudlusega JVM-i rakendusi, mis kasutavad JIT-kompilaatoreid.
  • Java on võimalik tõlkida registri-masina baitkoodiks, näiteks Dalvik virtuaalmasinas (koos JIT-i koostamisega) või AOT-i kompileerimisega ART-is.
  • Skriptikeel JavaScript täidetakse erinevate kõrgtehnoloogiliste "mootorite" abil, millega on peamised veebibrauserid varustatud, sageli koos JIT-i optimeerimise võimalusega. Paljud interpretaatorid on ehitatud baitkoodi abil, kuid Javascripti programme levitatakse lähtekoodidena.

Clipper-kompilaator loob käivitatava faili, mis sisaldab programmi lähtekoodist tõlgitud baitkoodi ja seda baitkoodi täitvat virtuaalmasinat.

Tavaliselt Java programmid kompileeritakse klassifailidesse (class-fail), mis sisaldavad Java baitkoodi. Need universaalsed failid kantakse üle erinevatesse sihtmärkmehhanismidesse.

Visual Basici varajastes rakendustes (kuni versioon 6) kasutati kõrgetasemelist Microsoft p-koodi[8]

DBMSis kasutati kõrgetasemelisi p-koode ja baitkoode, mõned BASICi ja Pascali rakendused.

Sun Microsystemsi standardse Open Firmware Openloaderi puhul esindab baitkood Forth operaatorit.

Näited[muuda | muuda lähteteksti]

Python[muuda | muuda lähteteksti]

Kood[11]:

>>> print("Hello, World!")
Hello, World!

Baitkood:

>>> import dis #importime moodul "dis" - Disassembler of Python byte code into mnemonics.
>>> dis.dis('print("Hello, World!")')
  1           0 LOAD_NAME                0 (print)
              2 LOAD_CONST               0 ('Hello, World!')
              4 CALL_FUNCTION            1
              6 RETURN_VALUE

Java[muuda | muuda lähteteksti]

Kood[12]:

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);
}

Baitkood:

 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

Arvustus[muuda | muuda lähteteksti]

Traditsiooniliselt on baitkood projekteeritud virnastatavate virtuaalmasinate stiilis, mis lihtsustab AST-i genereerimist, võimaldab kasutada lihtsamat ja kompaktsemat baitkoodi kodeeringut, lihtsustada interpretaatorit ja vähendada ühe koodimooduli juhendi täitmiseks vajaliku masinakoodi arvu. Teisalt sisaldavad sellised baitkoodivariandid antud programmiks rohkem juhiseid kui baitkoodid registreeritud virtuaalmasinates, mille tõttu interpretaator peab tegema rohkem kaudseid üleminekuid, mille puhul üleminekute ennustamine ei toimi hästi[2]. Registreeritud virtuaalmasinate baitkoodil on veidi suurem masinakoodide arv, kuid juhiste arv on umbes kaks korda väiksem kui stopp-baitkood ja interpretaator on kiirem kümnete protsentide võrra[2]. Samuti virnastamismasinate baitkood on optimeerimise jaoks keerulisem (väljendid muutuvad kaudseteks, seotud juhised ei ole rühmitatud, väljendid jagatakse mitme põhiploki vahel)[13] ja nõutakse korstna kasutamise õigsuse kontrollimist[14]

Vead stack-masinate baitkoodi kontrollimisel tõid kaasa hulga äärmiselt ohtlike haavatavusi, millest kümneid leiti AVM2 virtuaalmasinas, mida Adobe Flashi programmis kasutas skriptimiskeel ActionScript[15][16][17]. Samuti leiti haavatavusi mitmes varasemalt populaarses Java süsteemis (JVM).[18][19]

2010. aasta alguses, kahtlesid V8-kompilaatorite autorid (JavaScript-i keel, mida sageli rakendatakse baitkoodi kaudu)[20] ja Dart[21], et kiire ja tõhusa virtuaalse masina jaoks on vaja vaheprotseduuride baitkoode. Nendes projektides oli realiseeritud otsene JIT-i koostamine (koostamine käivitusajal) lähtekoodist otse masinakoodis.[22]

Viited[muuda | muuda lähteteksti]

  1. 1,0 1,1 Terence Parr. Language Implementation Patterns — Pragmatic Bookshelf, December 2009, ISBN 978-1-934356-45-6 «Part 3: Building Interpreters. Pattern 28 Register-Based Bytecode Interpreter»
  2. 2,0 2,1 2,2 Mall:Статья
  3. Bringing Performanceand Scalability toDynamic Languages{{|date= 05-2018 |bot=InternetArchiveBot }} // Mario Wolczko, Oracle 2012 слайд 7
  4. Руслан Богатырев. Летопись языков Паскаль, Мир ПК, № 04/2001
  5. Компиляторы: принципы, технологии и инструментарий — Вильямс, ISBN 9785845901897, стр 517 «12.2 Компиляторы Pascal»
  6. THE UCSD P-SYSTEM MUSEUM, 2004
  7. 7,0 7,1 Understanding .NET: A Tutorial and Analysis, David Chappell, David Wayne Chappell, 2002, ISBN 9780201741629 page 92
  8. 8,0 8,1 C# Versus Java / Dr. Dobb’s Journal February 2001
  9. http://www.javaworld.com/article/2077233/core-java/bytecode-basics.html 1996
  10. Алан Джок. "Компиляторы, интерпретаторы и байт-код". «Computerworld Россия», № 06, 2001. Vaadatud 18. mail 2015.
  11. Погружение в пучину интерпретатора Python. Ч1 / Python Байткод
  12. Java Байткод / Habr Site's 10 January 2011
  13. Mall:Статья: «virtual stack or virtual register VMs can be executed more efficiently using an interpreter. Virtual register machines can be an attractive alternative to stack architectures because they allow the number of executed VM instructions to be substantially reduced.»
  14. Gerwin Klein and Martin Wildmoser, Verified Bytecode Subroutines // Journal of Automated Reasoning 30.3-4 (2003): 363—398. «Bytecode verification is a static check for bytecode safety. Its purpose is to ensure that the JVM only executes safe code: no operand stack over- or underflows, no ill-formed instructions, no type errors»
  15. Mark Dowd (X-Force Researcher IBM Internet Security Systems), Leveraging the ActionScript Virtual MachineMall:Недоступная ссылка, IBM 2008 «if there was a way to execute AS3 instructions that had never been verified, it would be quite dangerous. Unverified instructions would be able to manipulate the native runtime stack … The attack works by manipulating a data structure used by the AVM2 verifier such that it doesn’t correctly verify the ActionScript instructions for a given method»
  16. Haifei Li, Understanding and Exploiting Flash ActionScript Vulnerabilities Arhiiviversioon, 2011 «Bytecode -> Verification process … ActionScript Vulnerabilities are due to various program flow calculating errors in the Verification/Generation Process (the Verification Flow and the Execution Flow are not the same)»
  17. Haifei Li (Microsoft), Inside AVM // REcon 2012, Montreal «Most Flash vulnerabilities are ActionScript-related … Faults on verification cause highly-dangerous JIT type confusion vulnerabilities. • highly-dangerous means perfect exploitation: bypassing ASLR+DEP, with %100 reliability, no heapSpray, no JITSpray. • JIT type confusion bugs are due to faults in the verification of AVM!»
  18. The last stage of delirium research group, Java and Java Virtual Machine security vulnerabilities and their exploitation techniques, BlackHat 2002: «The flaw stemmed from the fact that Bytecode Verifier did not properly perform the bytecode flow analysis»
  19. Verification of Bytecode in a Virtual machine Arhiiviversioon // International Journal of Advanced Research in Computer Science and Software Engineering Vol.3 Issue 3 March 2013, ISSN 2277-128X: «Java byte code verification has been studied extensively from a correctness perspective, and several vulnerabilities have been found and eliminated in this process»
  20. "Dynamic Machine Code Generation". Google.
  21. Loitsch, Florian. "Why Not a Bytecode VM?". Google.
  22. Dr. Axel Rauschmayer. "JavaScript myth: JavaScript needs a standard bytecode" (inglise).