Serializācija ir objekta stāvokļa saglabāšanas process baitu secībā; deserializācija ir šo baitu atjaunošanas process par dzīvo objektu. Java serializācijas API nodrošina standarta mehānismu izstrādātājiem, lai apstrādātu objektu sērijveidošanu. Šajā padomā jūs redzēsiet, kā sērijveidot objektu un kāpēc dažreiz ir nepieciešama serializācija. Uzzināsiet par Java izmantoto sērijas algoritmu un skatiet piemēru, kas ilustrē objekta sērijveida formātu. Līdz brīdim, kad esat pabeidzis, jums vajadzētu būt pārliecinātām par to, kā darbojas serializācijas algoritms un kādas entītijas tiek serializētas kā objekta daļa zemā līmenī.
Kāpēc nepieciešama serializācija?
Mūsdienu pasaulē tipiskai uzņēmuma lietojumprogrammai būs vairāki komponenti, un tā tiks izplatīta dažādās sistēmās un tīklos. Java valodā viss tiek attēlots kā objekti; ja divi Java komponenti vēlas sazināties savā starpā, ir nepieciešams datu apmaiņas mehānisms. Viens veids, kā to panākt, ir noteikt savu protokolu un pārsūtīt objektu. Tas nozīmē, ka saņēmējam ir jāzina protokols, kuru sūtītājs izmanto objekta atkārtotai izveidei, kas ļoti apgrūtinātu sarunu ar trešo pušu komponentiem. Tāpēc objekta pārsūtīšanai starp komponentiem ir nepieciešams vispārējs un efektīvs protokols. Šim nolūkam ir definēta serializācija, un Java komponenti izmanto šo protokolu objektu pārsūtīšanai.
1. attēlā parādīts klienta / servera komunikācijas augsta līmeņa skats, kur objekts tiek pārsūtīts no klienta uz serveri, izmantojot sērijveidu.
1. attēls. Augsta līmeņa serializācijas skats darbībā (noklikšķiniet, lai palielinātu)
Kā sērijveidot objektu
Lai serializētu objektu, jums jāpārliecinās, ka objekta klase ievieš java.io.Serializējams
saskarni, kā parādīts 1. sarakstā.
Uzskaitīšana 1. Serializable ieviešana
importēt java.io.Serializable; klase TestSerial ievieš Serializējamo {publisko baitu versija = 100; publisko baitu skaits = 0; }
1. sarakstā vienīgais, kas jums bija jādara savādāk, nekā izveidojot normālu klasi, ir java.io.Serializējams
interfeiss. The Serializējams
interfeiss ir marķiera interfeiss; tā vispār nedeklarē metodes. Tas norāda serializācijas mehānismu, ka klasi var seriālizēt.
Tagad, kad esat padarījis klasi piemērotu serializācijai, nākamais solis ir objekta faktiskā sērijveidošana. Tas tiek darīts, zvanot uz writeObject ()
metode java.io.ObjectOutputStream
klase, kā parādīts 2. sarakstā.
Saraksts 2. Zvanīšana writeObject ()
public static void main (String args []) izmet IOException {FileOutputStream fos = new FileOutputStream ("temp.out"); ObjectOutputStream oos = jauns ObjectOutputStream (fos); TestSerial ts = jauns TestSerial (); oos.writeObject (ts); oos.skalot (); oos.slēgt (); }
2. sarakstā tiek saglabāts TestSerial
objekts failā ar nosaukumu temp.out
. oos.writeObject (ts);
faktiski sāk serializācijas algoritmu, kas savukārt raksta objektu temp.out
.
Lai atkārtoti izveidotu objektu no pastāvīgā faila, jūs izmantosiet kodu 3. sarakstā.
Saraksts 3. Serializēta objekta atjaunošana
public static void main (String args []) izmet IOException {FileInputStream fis = new FileInputStream ("temp.out"); ObjectInputStream oin = jauns ObjectInputStream (fis); TestSerial ts = (TestSerial) oin.readObject (); System.out.println ("versija =" + ts.versija); }
3. sarakstā objekta atjaunošana notiek ar oin.readObject ()
metodes izsaukums. Šīs metodes izsaukums izskata neapstrādātos baitus, kurus mēs iepriekš saglabājām, un izveido aktīvu objektu, kas ir precīza sākotnējā objekta diagrammas kopija. Tā kā readObject ()
var lasīt jebkuru seriālizējamu objektu, ir nepieciešams nodot pareizajam tipam.
Izpildot šo kodu, tiks izdrukāts versija = 100
par standarta izvadi.
Objekta sērijveida formāts
Kā izskatās objekta sērijveida versija? Atcerieties, ka iepriekšējās sadaļas koda paraugs saglabāja sērijveida versiju TestSerial
objektu failā temp.out
. 4. sarakstā parādīts temp.out
, tiek rādīts heksadecimāli. (Lai redzētu izvadi heksadecimālā formātā, jums ir nepieciešams heksadecimālais redaktors.)
Saraksts 4. TestSerial sešpadsmitā forma
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.
Ja paskatās vēlreiz uz faktisko TestSerial
objektu, jūs redzēsiet, ka tajā ir tikai divi baitu dalībnieki, kā parādīts 5. sarakstā.
Saraksts 5. TestSerial baitu dalībnieki
publiskā baita versija = 100; publisko baitu skaits = 0;
Baitā mainīgā lielums ir viens baits, un tāpēc objekta kopējais lielums (bez galvenes) ir divi baiti. Bet, apskatot sērijveida objekta lielumu 4. sarakstā, jūs redzēsit 51 baitu. Pārsteigums! Kur radās papildu baiti, un kāda ir to nozīme? Tos ievieš serializācijas algoritms, un tie ir nepieciešami, lai objektu no jauna izveidotu. Nākamajā sadaļā jūs detalizēti izpētīsit šo algoritmu.
Java serializācijas algoritms
Tagad jums vajadzētu būt diezgan labām zināšanām par to, kā sertificēt objektu. Bet kā process notiek zem pārsega? Parasti serializācijas algoritms rīkojas šādi:
- Tajā tiek izrakstīti ar instanci saistītās klases metadati.
- Tā rekursīvi izraksta augstākās klases aprakstu, līdz atrod
java.lang.object
. - Kad metadatu informācija ir pabeigta, tā sākas ar faktiskajiem datiem, kas saistīti ar instanci. Bet šoreiz tas sākas no augstākās superklases.
- Tas rekursīvi raksta datus, kas saistīti ar gadījumu, sākot no mazākās superklases līdz visvairāk atvasinātajai klasei.
Es šai sadaļai esmu uzrakstījis citu objekta piemēru, kas aptvers visus iespējamos gadījumus. Jaunais seriālizējamais objekta paraugs ir parādīts 6. sarakstā.
Saraksts 6. Serializētā objekta paraugs
klases vecāks ievieš Serializējamo {int parentVersion = 10; } klase satur rīkus Serializējams {int saturVersion = 11; } publiskā klase SerialTest paplašina vecāku rīkus Serializable {int version = 66; satur con = jauns saturēt (); public int getVersion () {atgriešanās versija; } public static void main (String args []) izmet IOException {FileOutputStream fos = new FileOutputStream ("temp.out"); ObjectOutputStream oos = jauns ObjectOutputStream (fos); SerialTest st = jauns SerialTest (); oos.writeObject (st); oos.skalot (); oos.slēgt (); }}
Šis piemērs ir vienkāršs. Tas serializē tipa objektu SerialTest
, kas atvasināts no vecāks
un tam ir konteinera objekts, satur
. Šī objekta sērijveida formāts ir parādīts 7. sarakstā.
Saraksts 7. Objekta parauga sērijas forma
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
2. attēlā ir piedāvāts augsta līmeņa skatījums uz šī scenārija serializācijas algoritmu.
2. attēls. Serializācijas algoritma izklāsts
Apskatīsim detalizēti objekta sērijveida formātu un redzēsim, ko katrs baits pārstāv. Sāciet ar informāciju par serializācijas protokolu:
AC ED
:STREAM_MAGIC
. Norāda, ka tas ir serializācijas protokols.00 05
:STREAM_VERSION
. Serializācijas versija.0x73
:TC_OBJECT
. Norāda, ka tas ir jaunsObjekts
.
Serializācijas algoritma pirmais solis ir rakstīt klases aprakstu, kas saistīts ar instanci. Piemērs sērijveidā tipa objektu SerialTest
, tāpēc algoritms sākas, uzrakstot SerialTest
klasē.
0x72
:TC_CLASSDESC
. Norāda, ka šī ir jauna klase.00 0A
: Klases nosaukuma garums.53 65 72 69 61 6c 54 65 73 74
:SerialTest
, klases nosaukums.05 52 81 5A AC 66 02 F6
:SerialVersionUID
, šīs klases sērijas versijas identifikators.0x02
: Dažādi karogi. Šis konkrētais karodziņš saka, ka objekts atbalsta serializāciju.00 02
: Lauku skaits šajā klasē.
Pēc tam algoritms raksta lauku int versija = 66;
.
0x49
: Lauka tipa kods. 49 apzīmē "I", kas apzīmēInt
.00 07
: Lauka nosaukuma garums.76 65 72 73 69 6F 6E
:versija
, lauka nosaukums.
Un tad algoritms raksta nākamo lauku, satur con = jauns saturēt ();
. Šis ir objekts, tāpēc tas uzrakstīs šī lauka kanonisko JVM parakstu.
0x74
:TC_STRING
. Pārstāv jaunu virkni.00 09
: Virknes garums.4C 63 6F 6E 74 61 69 6E 3B
:Lkonteins;
, kanoniskais JVM paraksts.0x78
:TC_ENDBLOCKDATA
, objekta izvēles bloķēšanas datu beigas.
Nākamais algoritma solis ir rakstīt aprakstu vecāks
klase, kas ir tiešā klases augstākā klase SerialTest
.
0x72
:TC_CLASSDESC
. Norāda, ka šī ir jauna klase.00 06
: Klases nosaukuma garums.70 61 72 65 6E 74
:SerialTest
, klases nosaukums0E DB D2 BD 85 EE 63 7A
:SerialVersionUID
, šīs klases sērijas versijas identifikators.0x02
: Dažādi karogi. Šis karodziņš atzīmē, ka objekts atbalsta serializāciju.00 01
: Lauku skaits šajā klasē.
Tagad algoritms uzrakstīs lauka aprakstu vecāks
klasē. vecāks
ir viens lauks, int parentVersion = 100;
.
0x49
: Lauka tipa kods. 49 apzīmē "I", kas apzīmēInt
.00 0D
: Lauka nosaukuma garums.70 61 72 65 6E 74 56 65 72 73 69 6F 6E
:parentVersion
, lauka nosaukums.0x78
:TC_ENDBLOCKDATA
, šī objekta bloku datu beigas.0x70
:TC_NULL
, kas apzīmē faktu, ka vairs nav nevienas superklases, jo esam sasnieguši klases hierarhijas augšdaļu.
Līdz šim serializācijas algoritms ir uzrakstījis klases aprakstu, kas saistīts ar instanci un visām tās superklasēm. Pēc tam tā uzrakstīs faktiskos datus, kas saistīti ar gadījumu. Vispirms tā raksta vecāku klases locekļus:
00 00 00 0A
: 10, vērtībaparentVersion
.
Tad tas pāriet uz SerialTest
.
00 00 00 42
: 66, vērtībaversija
.
Daži nākamie baiti ir interesanti. Algoritmam ir jāuzraksta informācija par satur
objekts, parādīts 8. sarakstā.
Saraksts 8. Objekts satur
satur con = jauns saturēt ();
Atcerieties, ka serializācijas algoritms nav uzrakstījis klases aprakstu satur
klase vēl. Šī ir iespēja uzrakstīt šo aprakstu.
0x73
:TC_OBJECT
, apzīmējot jaunu objektu.0x72
:TC_CLASSDESC
.00 07
: Klases nosaukuma garums.63 6F 6E 74 61 69 6E
:satur
, klases nosaukums.FC BB E6 0E FB CB 60 C7
:SerialVersionUID
, šīs klases sērijas versijas identifikators.0x02
: Dažādi karogi. Šis karodziņš norāda, ka šī klase atbalsta serializāciju.00 01
: Lauku skaits šajā klasē.
Pēc tam algoritmam ir jāuzraksta apraksts satur
vienīgais lauks, int saturVersija = 11;
.
0x49
: Lauka tipa kods. 49 apzīmē "I", kas apzīmēInt
.00 0E
: Lauka nosaukuma garums.63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E
:includeVersion
, lauka nosaukums.0x78
:TC_ENDBLOCKDATA
.
Tālāk serializācijas algoritms pārbauda, vai satur
ir kādas vecāku klases. Ja tā būtu, algoritms sāktu rakstīt šo klasi; bet šajā gadījumā nav superklases satur
, tāpēc raksta algoritms TC_NULL
.
0x70
:TC_NULL
.
Visbeidzot, algoritms raksta faktiskos datus, kas saistīti ar satur
.
00 00 00 0B
: 11, vērtībaincludeVersion
.
Secinājums
Šajā padomā jūs esat redzējis, kā sertificēt objektu, un uzzinājāt, kā detalizēti darbojas serializācijas algoritms. Es ceru, ka šis raksts sniedz jums sīkāku informāciju par to, kas notiek, kad objektu faktiski sērijveida.
Par autoru
Sathiskumar Palaniappan ir vairāk nekā četru gadu pieredze IT nozarē, un viņš vairāk nekā trīs gadus strādā ar Java saistītām tehnoloģijām. Pašlaik viņš strādā kā sistēmas programmatūras inženieris Java tehnoloģiju centrā, IBM Labs. Viņam ir arī pieredze telekomunikāciju nozarē.
Resursi
- Izlasiet Java objektu sērijas specifikāciju. (Spec ir PDF.)
- "Saplaciniet savus objektus: atklājiet Java serializācijas API noslēpumus" (Todd M. Greanier, JavaWorld, 2000. gada jūlijs) piedāvā ieskatu sērijas procesa uzgriežņos un skrūvēs.
- 10. Nodaļa Java RMI (William Grosso, O'Reilly, 2001. gada oktobris) ir arī noderīga atsauce.
Šo stāstu "Atklāts Java sērijas algoritms" sākotnēji publicēja JavaWorld.