Bájtkód

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2022. augusztus 8-án felülvizsgált verziótól ; az ellenőrzéshez 1 szerkesztés szükséges .

A bájtkód ( bytecode ; angol  bytecode , néha p-kód is , p-kód hordozható kódból ) egy szabványos közbenső reprezentáció , amelybe egy számítógépes program automatikus módon lefordítható . Az ember által olvasható forráskóddal összehasonlítva a bájtkód egy olyan program kompakt reprezentációja, amelyet már elemeztek és értelmeztek . Kifejezetten kódol típusokat , hatóköröket és egyéb konstrukciókat. Technikai szempontból a bájtkód egy forráskódból fordító által generált alacsony szintű gépfüggetlen kód.

Sok modern programozási nyelv , különösen az értelmezett , bájtkódot használ a tolmács munkájának megkönnyítésére és felgyorsítására . A bájtkódra fordítás egy köztes hatékonyságú módszer a közvetlen értelmezés és a gépi kódba fordítás között.

Formájában a bájtkód hasonló a gépi kódhoz , de nem valódi processzorral , hanem virtuális géppel kell végrehajtani . A virtuális gép általában a megfelelő programozási nyelv értelmezője (néha JIT vagy AOT fordítóval kiegészítve ). A bájtkód és az azt végrehajtó virtuális gépek specifikációi nyelvenként nagyon eltérőek lehetnek: a bájtkód gyakran egy halmozott gép [1] utasításaiból áll , de használhatók a regisztergépek [2] [3] is. . A legtöbb bájtkódos utasítás azonban általában egy vagy több assembly nyelvi utasítással egyenértékű .

A bájtkódot azért nevezik így, mert minden műveleti kód hagyományosan egy bájt hosszú . Minden utasítás általában egy egybájtos műveleti kód (0-tól 255-ig), amelyet különféle paraméterek követhetnek, például egy regiszterszám vagy egy memóriacím .

Teljesítmény

A bájtkódos programokat általában egy bájtkód értelmező hajtja végre . A bájtkód előnye a nagyobb hatékonyság és hordozhatóság , vagyis ugyanaz a bájtkód végrehajtható különböző platformokon és architektúrákon , amelyekhez az értelmezőt implementálták. A közvetlenül értelmezett nyelvek azonban ugyanazt az előnyt nyújtják, mivel a bájtkód általában kevésbé absztrakt és kompaktabb, mint a forráskód, a bájtkód-értelmezés általában hatékonyabb, mint a tiszta forráskód-értelmezés vagy az AST -értelmezés . Ezenkívül a bájtkód értelmező gyakran egyszerűbb, mint a forráskód értelmező, és könnyebben átvihető (port) egy másik hardverplatformra.

A virtuális gépek nagy teljesítményű megvalósításai használhatják az értelmező és a JIT fordító kombinációját , amely a gyakran használt bájtkód-töredékeket gépi kódra fordítja a program végrehajtása során, miközben különféle optimalizálásokat alkalmaz. A JIT fordítás helyett egy AOT fordító használható , amely a bájtkódot előzetesen, a végrehajtás előtt gépi kódra fordítja.

Ugyanakkor lehetőség van olyan processzorok létrehozására, amelyekhez az adott bájtkód közvetlenül gépi kód (ilyen kísérleti processzorok készültek például a Java és a Forth nyelvekhez ).

Történelem

Az első bájtkódot használó rendszerek között volt az O-kód a BCPL-hez (1960-as évek), a Smalltalk (1976) [4] , a SIL (System Implementation Language) a Snobol-4-hez (1967), a p-code ( p-code , 1970-es évek, Niklaus Wirth hozzájárulásai ) a Pascal programozási nyelv hordozható fordítóihoz [5] [6] [7] .

A p-kód változatait széles körben használják a Pascal nyelv különféle megvalósításaiban, például az UCSD p-System- ben ( UCSD Pascal ). [nyolc]

Alkalmazás

A bájtkódot használó értelmezett nyelvek közé tartozik a Perl , a PHP (például a Zend Engine ), a Ruby (az 1.9-es verzió óta), a Python , az Erlang és még sok más.

Széles körben elterjedt platformok bájtkóddal [9] :

A Clipper fordítója létrehoz egy végrehajtható fájlt, amely tartalmazza a program forráskódjából lefordított bájtkódot és egy virtuális gépet, amely végrehajtja a bájtkódot.

A Java programokat általában osztályfájlokba fordítják, amely Java bájtkódot tartalmaz . Ezeket az általános fájlokat különböző célgépekre továbbítják.

A Visual Basic korai implementációi (a 6-os verzió előtt) magas szintű Microsoft p-kódot használtak [9]

Magas szintű p-kódokat és bájtkódokat használtak a DBMS -ben, a BASIC és a Pascal egyes megvalósításaiban .

A Sun Microsystems Open Firmware szabványában a bájtkód a Forth operátorokat jelöli .

Példák

Python

A kód:

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

Bájtkód:

>>> import # a " dis " modul importálása - Python bájtkód szétszedője a mnemonikába. >>> disz . dis ( 'print("Hello, World!")' ) 1 0 LOAD_NAME 0 ( print ) 2 LOAD_CONST 0 ( 'Hello, World!' ) 4 CALL_FUNCTION 1 6 RETURN_VALUE

Java

A kód:

külső : for ( int i = 2 ; i < 1000 ; i ++ ) { for ( int j = 2 ; j < i ; j ++ ) { if ( i % j == 0 ) tovább külső ; } Rendszer . ki . println ( i ); }

Bájtkód:

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 _ _ 25: iinc 2 , 1 28: goto 11 31: getstatic #84 ; //Java/lang/System.out:Ljava/io/PrintStream mező; 34: iload_1 35: invokevirtual #85 ; //Java/io/PrintStream.println módszer:(I)V 38: iinc 1 , 1 41: goto 2 44: return

Kritika

A bájtkódot hagyományosan a halmozott virtuális gépek stílusában tervezték, ami leegyszerűsíti az AST -ből történő generálást, egyszerűbb és kompaktabb bájtkódolást tesz lehetővé, leegyszerűsíti az értelmezőt, és csökkenti az egyetlen bájtkódos utasítás végrehajtásához szükséges gépi kód mennyiségét. Másrészt az adott program bájtkódjának ilyen változatai több utasítást tartalmaznak, mint a regiszter virtuális gépek bájtkódjai, ami miatt az interpreternek több közvetett ugrást kell végrehajtania, amelyre az elágazás előrejelzése nem működik jól [3] . A regiszteres virtuális gépek bájtkódjában valamivel nagyobb a gépi kódok mérete, de az utasítások száma a verem bájtkódhoz képest körülbelül kétszer kevesebb, az értelmező pedig több tíz százalékkal gyorsabb [3] . Emellett a veremgépek bájtkódja is nehezebben optimalizálható (a kifejezések implicitté válnak, a kapcsolódó utasítások nincsenek csoportosítva, a kifejezések több alapblokk között vannak elosztva ) [12] , és ellenőrizni kell a verem használatának helyességét [13] .

A veremgép bájtkód-ellenőrzési hibái számos rendkívül veszélyes sérülékenységhez vezettek, különösen az Adobe Flash-ben ActionScript-szkriptek futtatására használt AVM2 virtuális gépben [14] [15] [16] , és számos a korai népszerű Java futtatórendszerekben (JVM) . 17] [18]

A 2000-es évek végén és a 2010-es évek elején a V8 (JavaScripthez, gyakran bytecode-on keresztül) [19] és a Dart [20] fordítói megkérdőjelezték a köztes bájtkódok szükségességét a gyors és hatékony virtuális gépekhez. Ezek a projektek közvetlen JIT-fordítást (futás közbeni fordítást) valósítottak meg a forráskódokból közvetlenül a gépi kódba. [21]

Jegyzetek

  1. Terence Parr. Nyelvi megvalósítási minták – Pragmatikus könyvespolc, 2009. december, ISBN 978-1-934356-45-6 „3. rész: Tolmácsok építése. Pattern 27 Stack-Based Bytecode Interpreter” Archivált 2015. június 26-án a Wayback Machine -nél
  2. Terence Parr. Nyelvi megvalósítási minták – Pragmatikus könyvespolc, 2009. december, ISBN 978-1-934356-45-6 „3. rész: Tolmácsok építése. Pattern 28 Register-Based Bytecode Interpreter" Archivált 2015. június 26-án a Wayback Machine -nél
  3. 1 2 3 Yunhe Shi, David Gregg, Andrew Beatty, M. Anton Ertl. Virtual Machine Showdown: Stack Versus Registrs  //  VEE '05: A virtuális végrehajtási környezetekről szóló 1. ACM/USENIX nemzetközi konferencia előadásai. - Chicago, Illinois, USA: ACM, 2005. - P. 153-163 . — ISBN 1-59593-047-7 . - doi : 10.1145/1064979.1065001 .
  4. Teljesítmény és méretezhetőség a dinamikus nyelveken  (nem elérhető link) // Mario Wolczko, Oracle 2012 7. dia
  5. Ruszlan Bogatirev. Chronicle of Pascal Languages  Archiválva : 2015. május 30., a Wayback Machine , PC World, 2001/04 .
  6. Fordítók: alapelvek, technikák és eszközök archiválva : 2016. március 4., a Wayback Machine  - Williams, ISBN 9785845901897 , 517. oldal "12.2 Pascal fordítók"
  7. THE UCSD P-SYSTEM MUSEUM Archiválva : 2015. február 17., a Wayback Machine , 2004
  8. 1 2 A .NET megértése: oktatóanyag és elemzés archiválva : 2016. március 6., a Wayback Machine , David Chappell, David Wayne Chappell, 2002, ISBN 9780201741629 92. oldal
  9. 1 2 C# Versus Java Archiválva : 2016. április 6., a Wayback Machine / Dr. Dobb's Journal 2001. február
  10. http://www.javaworld.com/article/2077233/core-java/bytecode-basics.html Archiválva : 2015. május 19. a Wayback Machine 1996 -ban
  11. Alan Jock. Fordítók, tolmácsok és bájtkód . Computerworld Russia, No. 06, 2001. Letöltve: 2015. május 18. Archiválva : 2010. október 28.
  12. Ando Saabas, Tarmo Uustalu. Típusrendszerek veremalapú kód optimalizálásához  // Elektronikus jegyzetek az elméleti számítástechnikában. - 2007. - Kiadás. 190,1 . — 103-119. . - doi : 10.1016/j.entcs.2007.02.063 . Archiválva az eredetiből 2016. május 26-án. : "A virtuális verem vagy a virtuális regiszter virtuális gépei hatékonyabban hajthatók végre tolmács segítségével. A virtuális regisztergépek vonzó alternatívát jelenthetnek a veremarchitektúrák helyett, mivel lehetővé teszik a végrehajtott virtuális gép-utasítások számának jelentős csökkentését.”
  13. Gerwin Klein és Martin Wildmoser, Verified Bytecode szubrutinok archiválva : 2017. augusztus 10., a Wayback Machine // Journal of Automated Reasoning 30.3-4 (2003): 363-398. "A bájtkód-ellenőrzés a bájtkód biztonságának statikus ellenőrzése. Célja annak biztosítása, hogy a JVM csak biztonságos kódot hajtson végre: ne legyen operandusverem túl- vagy alulcsordulása, ne legyen rosszul formált utasítás, ne legyenek típushibák.
  14. Mark Dowd (X-Force Researcher IBM Internet Security Systems), Leveraging the ActionScript Virtual Machine  (nem elérhető hivatkozás) , IBM 2008 "Ha lenne mód olyan AS3 utasítások végrehajtására, amelyeket soha nem ellenőriztek, az meglehetősen veszélyes lenne. Az ellenőrizetlen utasítások képesek lennének a natív futásidejű verem manipulálására… A támadás az AVM2 ellenőrző által használt adatstruktúra manipulálásával működik, így az nem ellenőrzi megfelelően az ActionScript utasításait egy adott metódushoz."
  15. Haifei Li, A Flash ActionScript sebezhetőségeinek megértése és kihasználása Archiválva : 2013. november 26. , 2011 „Bájtkód -> Ellenőrzési folyamat… Az ActionScript sebezhetőségei az ellenőrzési/generálási folyamat különböző programfolyamat-számítási hibáiból fakadnak (az ellenőrzési folyamat és a végrehajtási folyamat nem ugyanaz)”
  16. Haifei Li (Microsoft), Inside AVM Archiválva : 2014. november 21., a Wayback Machine // REcon 2012, Montreal "A legtöbb Flash-sebezhetőség ActionScript-hez kapcsolódik... Az ellenőrzési hibák rendkívül veszélyes JIT típusú zavaros sebezhetőséget okoznak. • A rendkívül veszélyes tökéletes kihasználást jelent: ASLR+DEP megkerülése, 100%-os megbízhatóság, heapSpray, JITSpray nélkül. • A JIT típusú zavaros hibák az AVM ellenőrzésének hibáiból származnak!”
  17. A delírium kutatócsoport, a Java és a Java Virtual Machine biztonsági réseinek és kihasználási technikáinak utolsó szakasza Archiválva : 2016. március 12., a Wayback Machine , BlackHat 2002: "A hiba abból fakadt, hogy a Bytecode Verifier nem végezte el megfelelően a bájtkód-folyamelemzést "
  18. Bytecode ellenőrzése virtuális gépen Archiválva : 2013. április 30. // International Journal of Advanced Research in Computer Science and Software Engineering 3. kötet, 2013. március 3., ISSN 2277-128X: „A Java bájtos kódellenőrzést alaposan tanulmányozták a helyesség szempontjából, és számos sebezhetőséget találtak és szüntették meg ebben folyamat"
  19. Dinamikus gépi kód generálás . Google. Letöltve: 2015. május 18. Az eredetiből archiválva : 2013. szeptember 17..
  20. Loitsch, Florian Miért nem egy bytecode virtuális gép? . Google. Letöltve: 2015. május 18. Az eredetiből archiválva : 2013. május 12.
  21. Dr. Axel Rauschmayer. JavaScript-mítosz: A JavaScript szabványos  bájtkódot igényel . Letöltve: 2015. május 18. Az eredetiből archiválva : 2015. május 19.