Ohjelmointi

Java-sarjallisuusalgoritmi paljasti

Sarjaus on prosessi, jolla kohteen tila tallennetaan tavusarjaan; deserialisaatio on prosessi, jolla nämä tavut rakennetaan uudelleen eläväksi esineeksi. Java Serialization -sovellusliittymä tarjoaa kehittäjille vakiomekanismin objektien sarjallisuuden käsittelemiseksi. Tästä vinkistä näet, kuinka objekti sarjoitetaan ja miksi sarjallisuus on joskus tarpeen. Opit Java-sarjassa käytetystä sarjallisuusalgoritmista ja näet esimerkin, joka kuvaa objektin sarjoitettua muotoa. Siihen mennessä, kun olet valmis, sinulla on oltava vankka tieto siitä, miten sarjallisuusalgoritmi toimii ja mitkä yksiköt sarjoitetaan osana objektia matalalla tasolla.

Miksi sarjoitusta vaaditaan?

Nykymaailmassa tyypillisessä yrityssovelluksessa on useita komponentteja, ja se jaetaan useisiin järjestelmiin ja verkkoihin. Javassa kaikki esitetään esineinä; Jos kaksi Java-komponenttia haluaa olla yhteydessä toisiinsa, tietojenvaihtoon tarvitaan mekanismi. Yksi tapa saavuttaa tämä on määrittää oma protokolla ja siirtää objekti. Tämä tarkoittaa sitä, että vastaanottavan pään on tiedettävä lähettäjän käyttämä protokolla objektin uudelleen luomisessa, mikä tekisi hyvin vaikeaksi puhua kolmansien osapuolten komponenttien kanssa. Siksi objektin siirtämiseen komponenttien välillä on oltava yleinen ja tehokas protokolla. Sarjallisuus on määritelty tätä tarkoitusta varten, ja Java-komponentit käyttävät tätä protokollaa objektien siirtämiseen.

Kuvio 1 esittää korkean tason näkymän asiakas / palvelin-viestinnästä, jossa objekti siirretään asiakkaalta palvelimelle sarjallisuuden avulla.

Kuva 1. Korkean tason näkymä sarjoituksesta toiminnassa (napsauta suurentaaksesi)

Kuinka sarjata objekti

Objektin sarjallisuuden varmistamiseksi sinun on varmistettava, että objektiluokka toteuttaa java.io.Serialisoitavissa käyttöliittymä, kuten luettelossa 1 on esitetty.

Listaus 1. Serialisoitavissa oleva toteutus

 tuo java.io.Serializable; luokka TestSerial toteuttaa Serialisoitava {julkisen tavun versio = 100; julkisten tavujen määrä = 0; } 

Luettelossa 1 ainoa asia, jonka joudut tekemään eri tavalla kuin normaalin luokan luominen, on java.io.Serialisoitavissa käyttöliittymä. Sarjattavissa rajapinta on merkkiliitäntä; se ei ilmoita mitään menetelmiä. Se kertoo sarjallisuusmekanismille, että luokka voidaan sarjata.

Nyt kun olet asettanut luokan kelvolliseksi sarjallisuudeksi, seuraava askel on objektin sarjastaminen. Se tehdään soittamalla writeObject () menetelmä java.io.ObjectOutputStream luokka, kuten luettelossa 2 on esitetty.

Listaus 2. WriteObject () -kutsu

 public static void main (String args []) heittää IOException {FileOutputStream fos = new FileOutputStream ("temp.out"); ObjectOutputStream oos = uusi ObjectOutputStream (fos); TestSerial ts = uusi TestSerial (); oos.writeObject (ts); oos.huuhtele (); oos. sulje (); } 

Listaus 2 tallentaa Testisarja objekti tiedostossa nimeltä lämpötila. oos.writeObject (ts); todella käynnistää sarjallisuusalgoritmin, joka puolestaan ​​kirjoittaa objektin lämpötila.

Jos haluat luoda objektin uudelleen pysyvästä tiedostosta, käytä koodia luettelossa 3.

Luettelointi 3. Sarjoitetun objektin luominen uudelleen

 public static void main (String args []) heittää IOException {FileInputStream fis = uusi FileInputStream ("temp.out"); ObjectInputStream oin = uusi ObjectInputStream (fis); TestSerial ts = (TestSerial) oin.readObject (); System.out.println ("versio =" + ts.versio); } 

Luettelossa 3 objektin palauttaminen tapahtuu oin.readObject () menetelmäpuhelu. Tämä menetelmäkutsu lukee raakatavut, joita aiemmin käytimme, ja luo elävän objektin, joka on tarkka kopio alkuperäisestä objektikaaviosta. Koska readObject () voi lukea minkä tahansa sarjoitettavan objektin, vaaditaan valettu oikeaan tyyppiin.

Tämän koodin suorittaminen tulostaa versio = 100 vakiolähdössä.

Objektin sarjoitettu muoto

Miltä objektin sarjattu versio näyttää? Muista, että edellisen osan mallikoodi tallensi sarjanumeroidun version Testisarja objekti tiedostoon lämpötila. Luettelossa 4 näkyy lämpötila, näytetään heksadesimaaliluvulla. (Tarvitset heksadesimaalieditorin, jotta näet tuloksen heksadesimaalimuodossa.)

Luettelo 4. TestSerialin heksadesimaalimuoto

 AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65 73 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 05 63 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 78 70 00 64 

Jos katsot uudelleen todellista Testisarja objekti, näet, että sillä on vain kaksi tavua jäsentä, kuten luettelossa 5 on esitetty.

Luettelo 5. TestSerialin tavujäsenet

 julkisen tavun versio = 100; julkisten tavujen määrä = 0; 

Tavuisen muuttujan koko on yksi tavu, joten objektin kokonaiskoko (ilman otsikkoa) on kaksi tavua. Mutta jos tarkastelet sarjoitetun objektin kokoa Listing 4: ssä, näet 51 tavua. Yllätys! Mistä ylimääräiset tavut ovat peräisin, ja mikä on niiden merkitys? Ne otetaan käyttöön sarjaliikutusalgoritmilla, ja niitä tarvitaan objektin uudelleen luomiseksi. Seuraavassa osassa tutkit tätä algoritmia yksityiskohtaisesti.

Java: n sarjallisuusalgoritmi

Tähän mennessä sinulla pitäisi olla melko hyvä tieto objektin sarjallisuudesta. Mutta miten prosessi toimii konepellin alla? Sarjallisuusalgoritmi tekee yleensä seuraavat toimet:

  • Se kirjoittaa ilmentymään liittyvän luokan metatiedot.
  • Se kirjoittaa rekursiivisesti superluokan kuvauksen, kunnes löytää java.lang.object.
  • Kun se on kirjoittanut metatiedot, se alkaa todellisuuteen, joka liittyy ilmentymään. Mutta tällä kertaa se alkaa ylimmästä superluokasta.
  • Se kirjoittaa rekursiivisesti instanssiin liittyvät tiedot alkaen pienimmästä yläluokasta eniten johdettuun luokkaan.

Olen kirjoittanut tähän osioon toisen esimerkkiobjektin, joka kattaa kaikki mahdolliset tapaukset. Uusi sarjoitettava näyteobjekti näkyy luettelossa 6.

Listaus 6. Sarjasertifioitu näyte

 luokan vanhempi toteuttaa Serializable {int parentVersion = 10; } luokka sisältää työkaluja Serialisoitavissa {int includeVersion = 11; } public class SerialTest laajentaa vanhemman työkaluja Serializable {int version = 66; sisältää con = uusi sisältää (); public int getVersion () {return version; } public static void main (String args []) heittää IOException {FileOutputStream fos = new FileOutputStream ("temp.out"); ObjectOutputStream oos = uusi ObjectOutputStream (fos); SerialTest st = uusi SerialTest (); oos.writeObject (st); oos.huuhtele (); oos. sulje (); }} 

Tämä esimerkki on yksinkertainen. Se sarjoittaa tyypin objektin SerialTest, joka on johdettu vanhempi ja sillä on konttiobjekti, sisältää. Tämän objektin sarjoitettu muoto näkyy luettelossa 7.

Luettelo 7. Näyteobjektin sarjoitettu muoto

 AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65 73 74 05 52 81 5A AC 66 02 F6 02 00 02 49 00 07 76 65 72 73 69 6F 6E 4C 00 03 63 6F 6E 74 00 09 4C 63 6F 6E 74 61 69 6E 3B 78 72 00 06 70 61 72 65 6E 74 0E DB D2 BD 85 EE 63 7A 02 00 01 49 00 0D 70 61 72 65 6E 74 56 65 72 73 69 6F 6E 78 70 00 00 00 0A 00 00 00 42 73 72 00 07 63 6F 6E 74 61 69 6E FC BB E6 0E FB CB 60 C7 02 00 01 49 00 0E 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E 78 70 00 00 00 0B 

Kuva 2 tarjoaa korkean tason katsauksen tämän skenaarion sarjallisuusalgoritmiin.

Kuva 2. Sarjausalgoritmin pääpiirteet

Käytään läpi objektin sarjoitettu muoto ja katsotaan mitä kukin tavu edustaa. Aloita sarjallisuusprotokollan tiedoista:

  • AC ED: STREAM_MAGIC. Määrittää, että tämä on sarjaliitäntäprotokolla.
  • 00 05: STREAM_VERSION. Sarjaversio.
  • 0x73: TC_OBJECT. Määrittää, että tämä on uusi Esine.

Sarjallisuusalgoritmin ensimmäinen vaihe on kirjoittaa ilmentymään liittyvän luokan kuvaus. Esimerkki sarjoittaa tyypin objektin SerialTest, joten algoritmi alkaa kirjoittamalla kuvaus SerialTest luokassa.

  • 0x72: TC_CLASSDESC. Määrittää, että tämä on uusi luokka.
  • 00 0A: Luokan nimen pituus.
  • 53 65 72 69 61 6c 54 65 73 74: SerialTest, luokan nimi.
  • 05 52 81 5A AC 66 02 F6: SerialVersionUID, tämän sarjan sarjanumerotunniste.
  • 0x02: Erilaisia ​​lippuja. Tämä lippu sanoo, että objekti tukee sarjoitusta.
  • 00 02: Tähän luokkaan kuuluvien kenttien määrä.

Seuraavaksi algoritmi kirjoittaa kentän int-versio = 66;.

  • 0x49: Kenttätyyppikoodi. 49 edustaa "minä", joka tarkoittaa Int.
  • 00 07: Kentän nimen pituus.
  • 76 65 72 73 69 6F 6E: versio, kentän nimi.

Ja sitten algoritmi kirjoittaa seuraavan kentän, sisältää con = uusi sisältää ();. Tämä on objekti, joten se kirjoittaa tämän kentän kanonisen JVM-allekirjoituksen.

  • 0x74: TC_STRING. Edustaa uutta merkkijonoa.
  • 00 09: Merkkijonon pituus.
  • 4C 63 6F 6E 74 61 69 6E 3B: Lcontain;, kanoninen JVM-allekirjoitus.
  • 0x78: TC_ENDBLOCKDATA, objektin valinnaisen lohkotiedon loppu.

Seuraava algoritmin vaihe on kirjoittaa kuvaus vanhempi luokka, joka on välitön superluokka SerialTest.

  • 0x72: TC_CLASSDESC. Määrittää, että tämä on uusi luokka.
  • 00 06: Luokan nimi.
  • 70 61 72 65 6E 74: SerialTest, luokan nimi
  • 0E DB D2 BD 85 EE 63 7A: SerialVersionUID, tämän sarjan sarjanumerotunniste.
  • 0x02: Erilaisia ​​lippuja. Tämä lippu huomauttaa, että objekti tukee sarjoitusta.
  • 00 01: Tähän luokkaan kuuluvien kenttien määrä.

Nyt algoritmi kirjoittaa kentän kuvauksen vanhempi luokassa. vanhempi on yksi kenttä, int parentVersion = 100;.

  • 0x49: Kenttätyyppikoodi. 49 edustaa "minä", joka tarkoittaa Int.
  • 00 0D: Kentän nimen pituus.
  • 70 61 72 65 6E 74 56 65 72 73 69 6F 6E: parentVersion, kentän nimi.
  • 0x78: TC_ENDBLOCKDATA, tämän objektin lohkotietojen loppu.
  • 0x70: TC_NULL, mikä edustaa sitä, että ei ole enää superluokkia, koska olemme saavuttaneet luokkahierarkian kärjen.

Toistaiseksi sarjallisuusalgoritmi on kirjoittanut kuvauksen ilmentymään liittyvään luokkaan ja kaikkiin sen yläluokkiin. Seuraavaksi se kirjoittaa todellisuuteen liittyvät tiedot. Se kirjoittaa ensin vanhempien luokan jäsenet:

  • 00 00 00 0A: 10, arvo parentVersion.

Sitten se siirtyy SerialTest.

  • 00 00 00 42: 66, arvo versio.

Muutama seuraava tavu ovat mielenkiintoisia. Algoritmin on kirjoitettava tiedot sisältää objekti, näkyy luettelossa 8.

Listaus 8. Sisällytä objekti

 sisältää con = uusi sisältää (); 

Muista, että serialisointialgoritmi ei ole kirjoittanut luokan kuvausta sisältää luokassa vielä. Tämä on mahdollisuus kirjoittaa tämä kuvaus.

  • 0x73: TC_OBJECT, nimetään uusi esine.
  • 0x72: TC_CLASSDESC.
  • 00 07: Luokan nimen pituus.
  • 63 6F 6E 74 61 69 6E: sisältää, luokan nimi.
  • FC BB E6 0E FB CB 60 C7: SerialVersionUID, tämän sarjan sarjanumerotunniste.
  • 0x02: Erilaisia ​​lippuja. Tämä lippu osoittaa, että tämä luokka tukee sarjallisuutta.
  • 00 01: Tähän luokkaan kuuluvien kenttien määrä.

Seuraavaksi algoritmin on kirjoitettava kuvaus sisältääainoa kenttä, int sisältääVersio = 11;.

  • 0x49: Kenttätyyppikoodi. 49 edustaa "minä", joka tarkoittaa Int.
  • 00 0E: Kentän nimen pituus.
  • 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E: includeVersion, kentän nimi.
  • 0x78: TC_ENDBLOCKDATA.

Seuraavaksi sarjallisuusalgoritmi tarkistaa, onko sisältää on vanhempien luokat. Jos se tapahtui, algoritmi alkoi kirjoittaa kyseistä luokkaa; mutta tässä tapauksessa ei ole superluokkaa sisältää, joten algoritmi kirjoittaa TC_NULL.

  • 0x70: TC_NULL.

Lopuksi algoritmi kirjoittaa todelliset tiedot, jotka liittyvät sisältää.

  • 00 00 00 0B: 11, arvo includeVersion.

Johtopäätös

Tässä vihjeessä olet nähnyt kuinka sarjata objekti ja oppinut kuinka sarjallisuusalgoritmi toimii yksityiskohtaisesti. Toivon, että tämä artikkeli antaa sinulle tarkempia tietoja siitä, mitä tapahtuu, kun todellisuudessa sarjoitat objektin.

Kirjailijasta

Sathiskumar Palaniappanilla on yli neljän vuoden kokemus IT-alalta, ja hän on työskennellyt Java-tekniikoiden kanssa yli kolme vuotta. Tällä hetkellä hän työskentelee järjestelmäohjelmistoinsinöörinä Java Technology Centerissä, IBM Labs. Hänellä on myös kokemusta teleteollisuudesta.

Resurssit

  • Lue Java-objektin sarjallisuuseritelmä. (Spec on PDF.)
  • "Tasoita objektisi: Löydä Java Serialization -sovellusliittymän salaisuudet" (Todd M. Greanier, JavaWorld, heinäkuu 2000) tarjoaa katsauksen sarjakuvaprosessin muttereihin ja pultteihin.
  • 10 luku Java RMI (William Grosso, O'Reilly, lokakuu 2001) on myös hyödyllinen viite.

Tämän tarinan "Java-sarjan algoritmi paljasti" julkaisi alun perin JavaWorld.