1. Atkritumu pārstrādes mehānisma nozīme Ievērojama Java valodas iezīme ir atkritumu savākšanas mehānisma ieviešana, kas atrisina visgrūtāko atmiņas pārvaldības problēmu C++ programmētājiem, lai Java programmētājiem vairs nebūtu jāapsver atmiņas pārvaldība, rakstot programmas. Atkritumu savākšanas mehānisma dēļ Java objektiem vairs nav jēdziena "darbības joma", tikai objekta atsaucei ir "darbības joma".Atkritumu savākšana var efektīvi novērst atmiņas noplūdi un efektīvi izmantot dīkstāves atmiņu.
ps:内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。
2. Algoritmi atkritumu savākšanas mehānismos Java valodas specifikācijā nav skaidri norādīts, kuru atkritumu savākšanas algoritmu izmantot JVM, bet jebkuram atkritumu savākšanas algoritmam parasti ir jādara divas pamatlietas: (1) atrast bezjēdzīgus informācijas objektus; (2) Atgūt atmiņas vietu, ko aizņem bezjēdzīgi objekti, lai programma varētu atkal izmantot vietu.
1. Atsauces skaitīšanas savācējs 1.1 Algoritma analīze
Atsauces skaitīšana ir agrīna stratēģija atkritumu savācējiem. Šajā pieejā katram objekta gadījumam kaudzē ir atsauces skaits. Kad objekts ir izveidots un objekta instance ir piešķirta mainīgajam, mainīgo skaits tiek iestatīts uz 1. Ja jebkurš cits mainīgais tiek piešķirts kā atsauce uz šo objektu, skaits tiek pievienots ar 1 (a = b, tad objekta instances skaitītājs, uz kuru atsaucas b, ir +1), bet, ja atsauce uz objekta instanci ir pārsniegusi tās kalpošanas laiku vai ir iestatīta uz jaunu vērtību, objekta instances atsauces skaitītājs tiek atņemts ar 1. Jebkuru objekta gadījumu ar atsauces skaitītāju 0 var savākt kā atkritumus. Kad objekta instance tiek savākta atkritumos, jebkuras objekta instances atsauces skaitītājs ir mīnus 1. 1.2 Priekšrocības un trūkumi Nopelniem:
Atsauču skaita kolektoru var izpildīt ļoti ātri, sasaistot ar programmas darbību. Tas ir izdevīgi reāllaika vidē, kur programmas nav jāpārtrauc uz ilgu laiku. Trūkums:
Cirkulārās atsauces nevar noteikt. *Ja vecākobjektam ir atsauce uz bērnobjektu, bērnobjekts savukārt atsaucas uz vecākobjektu. Tādā veidā viņu citātu skaits nekad nevar būt 0. 1.3 Atsauču skaitīšanas algoritms nevar atrisināt cirkulārās atsauces problēmu, piemēram:
/** * Java学习交流QQ群:589809992 我们一起学Java! */public class Main { public static void main(String[] args) { MyObject object1 = new MyObject(); MyObject object2 = new MyObject(); object1.object = object2; object2.object = object1; object1 = null; object2 = null; }} Pēdējie divi teikumi piešķir objektu1 un objektu2 nullei, kas nozīmē, ka objektiem, uz kuriem norāda objekts1 un objekts2, vairs nevar piekļūt, bet, tā kā tie attiecas viens uz otru, to atsauces skaitītāji nav 0, tāpēc atkritumu savācējs tos nekad nepārstrādās.
2. Izsekošanas kolektors vai marķēšanas un slaucīšanas algoritms 2.1 Saknes meklēšanas algoritms
Saknes meklēšanas algoritms tiek ieviests no grafu teorijas diskrētajā matemātikā, programma visas atsauces attiecības uzskata par grafiku, sākot no mezgla GC ROOT, meklējot atbilstošo atsauces mezglu, pēc šī mezgla atrašanas, turpinot meklēt šī mezgla atsauces mezglu, kad tiek meklēti visi atsauces mezgli, atlikušie mezgli tiek uzskatīti par neatsaucētiem mezgliem, tas ir, bezjēdzīgiem mezgliem. Java, ko var izmantot kā GC sakni 1. Objekti, uz kuriem atsaucas virtuālās mašīnas stekā (lokālo mainīgo tabula) 2. Objekts, uz kuru atsaucas statiskais atribūts metodes apgabalā 3. Objekts, uz kuru atsaucas konstante metodes apgabalā 4. Atsauces objekti lokālajā metožu stekā (vietējie objekti)
2.2 Izsekošanas algoritma shematiska diagramma
![]()
2.3 Marķieru klīringa algoritma analīze
Tagu tīrīšanas algoritms skenē no saknes kolekcijas, atzīmē izdzīvojušos objektus un pēc tam skenē visu vietu, lai atrastu neatzīmētus objektus, lai tos pārstrādātu, kā parādīts iepriekš redzamajā attēlā. Tagu tīrīšanas algoritmam nav jāpārvieto objekti, un tas apstrādā tikai neizdzīvojušos objektus, kas ir ārkārtīgi efektīvi, ja ir daudz izdzīvojušu objektu, bet, tā kā tagu tīrīšanas algoritms tieši pārstrādā neizdzīvojušos objektus, tas izraisīs atmiņas sadrumstalotību.
3. Saspiešanas algoritms vai etiķetes apdares algoritms
![]()
Tag-finish algoritms izmanto to pašu metodi kā tag-clear algoritms, lai marķētu objektus, bet tas ir atšķirīgs, kad iztīrīšana, pēc tam, kad ir atgūta vieta, ko aizņem neizdzīvojušie objekti, tas pārvietos visus izdzīvojušos objektus uz brīvo vietu kreisajā galā un atjauninās atbilstošo rādītāju. Tagu apdares algoritms ir balstīts uz tagu tīrīšanas algoritmu un pārvieto objektus, tāpēc tas ir dārgāks, bet tas atrisina atmiņas sadrumstalotības problēmu. Ieviešot kolektorus, kuru pamatā ir saspiešanas algoritms, parasti tiek pievienoti rokturi un rokturu tabulas.
4. Kopēšanas algoritms (saspiešanas kolektors)
![]()
Algoritms tiek ierosināts, lai pārvarētu roktura pieskaitāmās izmaksas un atrisinātu kaudzes atkritumu savākšanu. Kad objekts ir pilns, atkritumu savākšana, kuras pamatā ir kopēšanas algoritms, skenē aktīvo objektu no saknes kopas un kopē katru aktīvo objektu uz brīvo seju (tā, lai starp aktīvā objekta aizņemto atmiņu nebūtu brīvu caurumu), lai brīvā virsma kļūtu par objekta seju, sākotnējā objekta seja kļūtu par brīvo seju, un programma piešķir atmiņu jaunajā objekta sejā. Tipiska atkritumu savākšana, kuras pamatā ir pārvarēšanas algoritms, ir apturēšanas un kopēšanas algoritms, kas sadala kaudzi objektu sejās un brīvās zonas sejās, un programma pārtrauc izpildi, pārslēdzoties starp objektu sejām un brīvās zonas sejām.
5. Paaudžu kolekcionārs
![]()
Paaudžu atkritumu pārstrādes stratēģijas pamatā ir fakts, kaDažādu objektu dzīves cikls ir atšķirīgs。 Tāpēc objekti ar dažādiem dzīves cikliem var izmantot dažādus pārstrādes algoritmus, lai uzlabotu pārstrādes efektivitāti.
Jaunā paaudze 1. Visi jaunradītie objekti vispirms tiek ievietoti jaunākajā paaudzē. Jaunākās paaudzes mērķis ir pēc iespējas ātrāk savākt tos objektus ar īsu dzīves ciklu.
2. Jaunās paaudzes atmiņa ir sadalīta vienā Ēdenes reģionā un divās izdzīvojušo (izdzīvojušo0, izdzīvojušo1) zonās pēc attiecības 8:1:1. Viena Ēdenes zona, divas izdzīvojušo zonas (kopumā). Lielākā daļa objektu ir nārstojuši Ēdenes apgabalā. Kad arī izdzīvojušais0 apgabals ir pilns, ēdenes apgabals un izdzīvojušā 0 apgabals tiek kopēts uz citu izdzīvojušo1 apgabalu, un pēc tam ēdes un izdzīvojušājo0 apgabals tiek iztukšots, un tad izdzīvojušais0 apgabals ir tukšs, un pēc tam tiek apmainīts izdzīvojušais0 un izdzīvojušais1 apgabals. Tas ir, saglabājiet izdzīvojušo1 zonu tukšu utt.
3. Ja izdzīvojušā 1 platība nav pietiekama, lai glabātu izdzīvojušos ēdenes un izdzīvojušo0 objektus, izdzīvojušie objekti tiek glabāti tieši vecajā laikmetā. Ja arī vecums ir pilns, tas izraisīs pilnu GC, tas ir, jaunā paaudze un vecā paaudze tiks pārstrādāta
4. Jaunās paaudzes GC sauc arī par Minor GC, un MinorGC biežums ir salīdzinoši augsts (tas ne vienmēr tiek iedarbināts, kad Ēdenes apgabals ir pilns)
Vecā paaudze
1. Objekti, kas joprojām ir dzīvi pēc N atkritumu pārstrādes pieredzes jaunākajā paaudzē, tiks ievietoti vecākajā paaudzē. Tāpēc var uzskatīt, ka vecā paaudze tiek glabāta dažos objektos ar ilgu dzīves ciklu.
2. Atmiņa ir arī daudz lielāka nekā jaunās paaudzes atmiņa (aptuvenā attiecība ir 1:2), kad vecuma atmiņa ir pilna, tiek iedarbināts Major GC, tas ir, Full GC, Full GC frekvence ir salīdzinoši zema, vecuma objekta izdzīvošanas laiks ir salīdzinoši ilgs, un izdzīvošanas rādītāja atzīme ir augsta.
Pastāvīgā paaudze Izmanto, lai glabātu statiskus failus, piemēram, Java klases, metodes utt. Pastāvīgajām paaudzēm nav būtiskas ietekmes uz atkritumu savākšanu, bet dažas lietojumprogrammas var dinamiski ģenerēt vai izsaukt dažas klases, piemēram, Hibernēt utt., Un šajā gadījumā ir jāiestata salīdzinoši liela pastāvīga ģenerēšanas telpa, lai saglabātu šīs jaunās klases izpildes laikā.
3. GC (atkritumu savācējs)Jaunās paaudzes kolekcionāru izmantotie kolektori: Serial, PraNew, Parallel Scavenge Kolekcionāri, ko izmanto vecuma kolekcionāri: sērijveida vecais, paralēlais vecais, CMS
![]()
Sērijveida kolektors (replikācijas algoritms) Jaunās paaudzes viena vītņa kolektori, marķēšana un tīrīšana ir viena vītņota, ar priekšrocību, ka tie ir vienkārši un efektīvi.
Sērijveida vecais kolektors (etiķetes apdares algoritms) Vecuma viena pavediena savācējs, sērijveida kolekcionāra vecuma versija.
ParNew kolektors (stop-copy algoritms) Jaunās paaudzes kolektoru var uzskatīt par seriālā kolektora daudzpavedienu versiju, kurai ir labāka veiktspēja nekā seriālam daudzkodolu CPU vidē.
Paralēlais Scavenge Collector (Stop-Copy algoritms) Paralēlie kolektori augstai caurlaidspējai un efektīvai CPU izmantošanai. Caurlaidspēja parasti ir 99%, un caurlaidspēja = lietotāja pavediena laiks / (lietotāja pavediena laiks + GC pavediena laiks). Tas ir piemērots tādiem scenārijiem kā fona lietojumprogrammas, kurām attiecīgi nav nepieciešama augsta mijiedarbība.
Paralēls vecais kolektors (Stop-Copy algoritms) Vecāka Parallel Scavenge kolektora versija, paralēlais kolektors, ar caurlaides prioritāti
CMS (vienlaicīga atzīmju slaucīšana) kolektors (atzīmes tīrīšanas algoritms) Augsta vienlaicīgība, zema pauze, īsākais GC atkopšanas pauzes laiks, augsts CPU lietojums, ātrs reakcijas laiks, īss pauzes laiks un daudzkodolu CPU, kas cenšas sasniegt augstu reakcijas laiku
4. GC ieviešanas mehānismsTā kā objekts ir apstrādāts dažādās paaudzēs, arī atkritumu savākšanas platība un laiks ir atšķirīgi. Ir divu veidu GC: Scavenge GC un Full GC.
Scavenge GC Parasti, kad tiek ģenerēts jauns objekts un neizdodas pieteikties uz vietu Ēdenē, tiks aktivizēts Scavenge GC, kas GC Ēdenes apgabalu, notīrīs neizdzīvojušos objektus un pārvietos izdzīvojušos objektus uz Survivor apgabalu. Pēc tam sakārtojiet divas Survivor zonas. GC šādā veidā tiek veikts jaunākās paaudzes Ēdenes apgabalā un neietekmē vecāko paaudzi. Tā kā lielākā daļa objektu sākas no Ēdenes apgabala, un Ēdenes apgabals nav piešķirts ļoti daudz, Ēdenes apgabala GC tiek veikts bieži. Tāpēc šeit parasti ir jāizmanto ātri un efektīvi algoritmi, lai pēc iespējas ātrāk padarītu Ēdeni brīvu.
Pilns GC Sakārtojiet visu kaudzi, ieskaitot jaunos, pastāvīgos un permus. Full GC ir lēnāks nekā Scavenge GC, jo tas prasa pārstrādāt visu kaudzi, tāpēc Full GC skaits ir jāsamazina, cik vien iespējams. Liela daļa no JVM regulēšanas procesa ir FullGC regulēšana. Pilnu GC var izraisīt šādi iemesli: 1. Pastāvīgais ir uzrakstīts pilns 2. Perma ir uzrakstīta pilna 3. System.gc() tiek parādīts kā izsaukums 4. Heap domēna piešķiršanas stratēģija dinamiski mainās pēc pēdējās GC
5. Java ar GC būs arī atmiņas noplūdes problēmas1. Statisko savākšanas klašu, piemēram, HashMap, Vector utt., izmantošana ir visvairāk pakļauta atmiņas noplūdei, un šo statisko mainīgo dzīves cikls ir tāds pats kā lietojumprogrammai, un visus objektus nevar atbrīvot, jo tos vienmēr piemēros Vector un citi. Statiskais vektors v = jauns vektors (); for (int i = 1; i<100; i++) { Objekts o = jauns Objekts(); v.add(o); o = nulle; } Šajā piemērā koda stekā ir atsauce v objektam Vector un atsauce o objektam Object. Cilpā For mēs turpinām ģenerēt jaunus objektus, pēc tam pievienojot tos objektam Vector un pēc tam anulējot o atsauci. Jautājums ir, ja o atsauce tiek anulēta, ja rodas GC, vai mūsu izveidoto objekta objektu var pārstrādāt GC? Atbilde ir nē. Jo, kad GC izseko atsauces kodu kaudzē, tas atrod v atsauces, un, ja turpināsiet izsekot, jūs atradīsit, ka atmiņas telpā, uz kuru norāda v atsauces, ir atsauces uz objekta objektiem. Tas nozīmē, ka, lai gan o atsauce ir iztukšota, joprojām ir citas atsauces uz objektu Objekts, kurām var piekļūt, tāpēc GC nevar tās atbrīvot. Ja pēc šīs cilpas objekta objekts neietekmē programmu, tad mēs pieņemam, ka Java programmai ir atmiņas noplūde. 2. Dažādi savienojumi, datu bāzes savienojumi, tīkla savienojumi, IO savienojumi utt. Neparāda zvanu tuvu aizvēršanai, un GC tos nepārstrādā, kā rezultātā rodas atmiņas noplūde. 3. Klausītāju izmantošana var izraisīt atmiņas noplūdi arī tad, ja klausītājs netiek izdzēsts, atbrīvojot objektu.
|