1. Η σημασία του μηχανισμού ανακύκλωσης σκουπιδιών Ένα αξιοσημείωτο χαρακτηριστικό της γλώσσας Java είναι η εισαγωγή ενός μηχανισμού συλλογής σκουπιδιών, ο οποίος λύνει το πιο ενοχλητικό πρόβλημα διαχείρισης μνήμης για προγραμματιστές C++, έτσι ώστε οι προγραμματιστές Java να μην χρειάζεται πλέον να εξετάζουν τη διαχείριση μνήμης όταν γράφουν προγράμματα. Λόγω του μηχανισμού συλλογής σκουπιδιών, τα αντικείμενα στην Java δεν έχουν πλέον την έννοια του "πεδίου", μόνο η αναφορά του αντικειμένου έχει "εύρος".Η συλλογή σκουπιδιών μπορεί να αποτρέψει αποτελεσματικά τη διαρροή μνήμης και να χρησιμοποιήσει αποτελεσματικά τη μνήμη αδράνειας.
ps:内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。
2. Αλγόριθμοι σε μηχανισμούς συλλογής απορριμμάτων Η προδιαγραφή της γλώσσας Java δεν καθορίζει ρητά ποιον αλγόριθμο συλλογής σκουπιδιών θα χρησιμοποιηθεί στο JVM, αλλά κάθε αλγόριθμος συλλογής σκουπιδιών πρέπει γενικά να κάνει δύο βασικά πράγματα: (1) να βρει άχρηστα αντικείμενα πληροφοριών. (2) Ανακτήστε το χώρο μνήμης που καταλαμβάνεται από άχρηστα αντικείμενα, έτσι ώστε ο χώρος να μπορεί να χρησιμοποιηθεί ξανά από το πρόγραμμα.
1. Συλλέκτης καταμέτρησης αναφοράς 1.1 Ανάλυση αλγορίθμου
Η καταμέτρηση αναφορών είναι μια πρώιμη στρατηγική στους συλλέκτες σκουπιδιών. Σε αυτήν την προσέγγιση, υπάρχει ένας αριθμός αναφορών για κάθε παρουσία αντικειμένου στο σωρό. Όταν δημιουργείται ένα αντικείμενο και η παρουσία του αντικειμένου εκχωρείται σε μια μεταβλητή, ο αριθμός μεταβλητών ορίζεται σε 1. Όταν οποιαδήποτε άλλη μεταβλητή εκχωρείται ως αναφορά σε αυτό το αντικείμενο, η μέτρηση προστίθεται κατά 1 (a = b, τότε ο μετρητής της παρουσίας αντικειμένου που αναφέρεται από το b είναι +1), αλλά όταν μια αναφορά σε μια παρουσία αντικειμένου έχει υπερβεί τη διάρκεια ζωής της ή έχει οριστεί σε μια νέα τιμή, ο μετρητής αναφοράς της παρουσίας αντικειμένου αφαιρείται κατά 1. Οποιαδήποτε περίπτωση ενός αντικειμένου με μετρητή αναφοράς 0 μπορεί να συλλεχθεί ως σκουπίδια. Όταν μια παρουσία αντικειμένου συλλέγεται σκουπίδια, ο μετρητής αναφοράς οποιασδήποτε παρουσίας αντικειμένου στην οποία αναφέρεται είναι μείον 1. 1.2 Πλεονεκτήματα και μειονεκτήματα Αξία:
Ο συλλέκτης μέτρησης αναφοράς μπορεί να εκτελεστεί πολύ γρήγορα, συνυφασμένος με την εκτέλεση του προγράμματος. Είναι πλεονεκτικό για περιβάλλοντα σε πραγματικό χρόνο όπου τα προγράμματα δεν χρειάζεται να διακόπτονται για μεγάλα χρονικά διαστήματα. Έλλειψη:
Δεν είναι δυνατός ο εντοπισμός κυκλικών παραπομπών. *Εάν το γονικό αντικείμενο έχει μια αναφορά σε ένα θυγατρικό αντικείμενο, το θυγατρικό αντικείμενο με τη σειρά του αναφέρεται στο γονικό αντικείμενο. Με αυτόν τον τρόπο, ο αριθμός των αναφορών τους δεν μπορεί ποτέ να είναι 0. 1.3 Ο αλγόριθμος μέτρησης αναφορών δεν μπορεί να λύσει το πρόβλημα κυκλικής αναφοράς, για παράδειγμα:
/** * 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; }} Οι δύο τελευταίες προτάσεις εκχωρούν το αντικείμενο1 και το αντικείμενο2 σε null, πράγμα που σημαίνει ότι τα αντικείμενα στα οποία δείχνουν το αντικείμενο1 και το αντικείμενο2 δεν είναι πλέον προσβάσιμα, αλλά επειδή αναφέρονται το ένα στο άλλο, οι μετρητές αναφοράς τους δεν είναι 0, επομένως ο συλλέκτης απορριμμάτων δεν θα τα ανακυκλώσει ποτέ.
2. Ανίχνευση συλλέκτη ή αλγόριθμος σήμανσης και σάρωσης 2.1 Αλγόριθμος αναζήτησης ρίζας
Ο αλγόριθμος αναζήτησης ρίζας εισάγεται από τη θεωρία γραφημάτων στα διακριτά μαθηματικά, το πρόγραμμα θεωρεί όλες τις σχέσεις αναφοράς ως γράφημα, ξεκινώντας από έναν κόμβο GC ROOT, αναζητώντας τον αντίστοιχο κόμβο αναφοράς, αφού βρει αυτόν τον κόμβο, συνεχίζοντας να αναζητά τον κόμβο αναφοράς αυτού του κόμβου, όταν αναζητούνται όλοι οι κόμβοι αναφοράς, οι υπόλοιποι κόμβοι θεωρούνται κόμβοι χωρίς αναφορά, δηλαδή άχρηστοι κόμβοι. java που μπορεί να χρησιμοποιηθεί ως GC Root 1. Αντικείμενα που αναφέρονται στη στοίβα εικονικής μηχανής (πίνακας τοπικών μεταβλητών) 2. Το αντικείμενο που αναφέρεται από το στατικό χαρακτηριστικό στην περιοχή της μεθόδου 3. Το αντικείμενο που αναφέρεται από τη σταθερά στην περιοχή της μεθόδου 4. Αναφερόμενα αντικείμενα στη στοίβα τοπικής μεθόδου (εγγενή αντικείμενα)
2.2 Σχηματικό διάγραμμα αλγορίθμου ανίχνευσης
![]()
2.3 Ανάλυση αλγορίθμου εκκαθάρισης δεικτών
Ο αλγόριθμος εκκαθάρισης ετικετών σαρώνει από τη ριζική συλλογή, επισημαίνει τα σωζόμενα αντικείμενα και, στη συνέχεια, σαρώνει ολόκληρο τον χώρο για ανακύκλωση αντικειμένων χωρίς ετικέτα, όπως φαίνεται στην παραπάνω εικόνα. Ο αλγόριθμος εκκαθάρισης ετικετών δεν χρειάζεται να μετακινεί αντικείμενα και επεξεργάζεται μόνο μη σωζόμενα αντικείμενα, κάτι που είναι εξαιρετικά αποτελεσματικό όταν υπάρχουν πολλά σωζόμενα αντικείμενα, αλλά επειδή ο αλγόριθμος εκκαθάρισης ετικετών ανακυκλώνει απευθείας μη επιζώντα αντικείμενα, θα προκαλέσει κατακερματισμό της μνήμης.
3. Αλγόριθμος συμπίεσης ή αλγόριθμος φινιρίσματος ετικετών
![]()
Ο αλγόριθμος φινιρίσματος ετικετών χρησιμοποιεί την ίδια μέθοδο με τον αλγόριθμο διαγραφής ετικετών για την επισήμανση αντικειμένων, αλλά είναι διαφορετικός κατά την εκκαθάριση, αφού ανακτήσει τον χώρο που καταλαμβάνουν τα μη σωζόμενα αντικείμενα, θα μετακινήσει όλα τα σωζόμενα αντικείμενα στον ελεύθερο χώρο στο αριστερό άκρο και θα ενημερώσει τον αντίστοιχο δείκτη. Ο αλγόριθμος tag-finish βασίζεται στον αλγόριθμο tag-purge και μετακινεί αντικείμενα, επομένως είναι πιο ακριβός, αλλά λύνει το πρόβλημα του κατακερματισμού της μνήμης. Στην υλοποίηση συλλεκτών με βάση τον αλγόριθμο Compacting, προστίθενται γενικά λαβές και πίνακες λαβών.
4. Αλγόριθμος αντιγραφής (Συλλέκτης συμπίεσης)
![]()
Ο αλγόριθμος προτείνεται για να ξεπεραστεί η επιβάρυνση της λαβής και να λυθεί η συλλογή σκουπιδιών των συντριμμιών σωρού. Όταν το αντικείμενο είναι γεμάτο, η συλλογή απορριμμάτων με βάση τον αλγόριθμο αντιγραφής σαρώνει το ενεργό αντικείμενο από το ριζικό σύνολο και αντιγράφει κάθε ενεργό αντικείμενο στην ελεύθερη όψη (έτσι ώστε να μην υπάρχουν ελεύθερες οπές μεταξύ της μνήμης που καταλαμβάνει το ενεργό αντικείμενο), έτσι ώστε η ελεύθερη επιφάνεια να γίνει η όψη του αντικειμένου, η αρχική όψη αντικειμένου γίνεται η ελεύθερη όψη και το πρόγραμμα εκχωρεί μνήμη στη νέα όψη αντικειμένου. Μια τυπική συλλογή σκουπιδιών που βασίζεται στον αλγόριθμο αντιμετώπισης είναι ο αλγόριθμος stop-and-copy, ο οποίος χωρίζει το σωρό σε όψεις αντικειμένων και όψεις ελεύθερης περιοχής και το πρόγραμμα διακόπτει την εκτέλεση κατά την εναλλαγή μεταξύ όψεων αντικειμένων και όψεων ελεύθερης περιοχής.
5. Συλλέκτης γενεών
![]()
Η στρατηγική ανακύκλωσης σκουπιδιών γενεών βασίζεται στο γεγονός ότιΟ κύκλος ζωής διαφορετικών αντικειμένων είναι διαφορετικός。 Επομένως, αντικείμενα με διαφορετικούς κύκλους ζωής μπορούν να υιοθετήσουν διαφορετικούς αλγόριθμους ανακύκλωσης για να βελτιώσουν την αποτελεσματικότητα της ανακύκλωσης.
Νέα γενιά 1. Όλα τα αντικείμενα που δημιουργούνται πρόσφατα τοποθετούνται πρώτα στη νεότερη γενιά. Ο στόχος της νεότερης γενιάς είναι να συλλέξει εκείνα τα αντικείμενα με σύντομο κύκλο ζωής όσο το δυνατόν γρηγορότερα.
2. Η μνήμη νέας γενιάς χωρίζεται σε μία περιοχή της Εδέμ και σε δύο ζώνες επιζώντων (survivor0, survivor1) σύμφωνα με την αναλογία 8:1:1. Μία ζώνη Εδέμ, δύο ζώνες Survivor (γενικά). Τα περισσότερα από τα αντικείμενα γεννιούνται στην περιοχή της Εδέμ. Όταν η περιοχή survivor0 είναι επίσης γεμάτη, η περιοχή eden και η περιοχή survivor 0 αντιγράφονται σε μια άλλη περιοχή survivor1 και, στη συνέχεια, η περιοχή eden και survivor0 αδειάζουν, και στη συνέχεια η περιοχή survivor0 είναι κενή και, στη συνέχεια, η περιοχή survivor0 και η περιοχή survivor1 ανταλλάσσονται. Δηλαδή, κρατήστε την περιοχή survivor1 κενή και ούτω καθεξής.
3. Όταν η περιοχή του επιζώντος 1 δεν είναι αρκετή για την αποθήκευση των σωζόμενων αντικειμένων της Εδέμ και του επιζώντος0, τα σωζόμενα αντικείμενα αποθηκεύονται απευθείας στην παλιά εποχή. Αν γεμίσει και το γήρας, θα πυροδοτήσει ένα πλήρες GC, δηλαδή θα ανακυκλωθεί η νέα γενιά και η παλιά γενιά
4. Το GC της νέας γενιάς ονομάζεται επίσης Minor GC και η συχνότητα του MinorGC είναι σχετικά υψηλή (δεν ενεργοποιείται απαραίτητα όταν η περιοχή της Εδέμ είναι γεμάτη)
Παλιά γενιά
1. Αντικείμενα που είναι ακόμα ζωντανά μετά την εμπειρία της ανακύκλωσης σκουπιδιών Ν στη νεότερη γενιά θα τοποθετηθούν στην παλαιότερη γενιά. Επομένως, μπορεί να θεωρηθεί ότι η παλιά γενιά αποθηκεύεται σε ορισμένα αντικείμενα με μεγάλο κύκλο ζωής.
2. Η μνήμη είναι επίσης πολύ μεγαλύτερη από αυτή της νέας γενιάς (η κατά προσέγγιση αναλογία είναι 1:2), όταν η μνήμη της τρίτης ηλικίας είναι πλήρης, ενεργοποιείται το Major GC, δηλαδή Full GC, η συχνότητα του Full GC είναι σχετικά χαμηλή, ο χρόνος επιβίωσης του αντικειμένου γήρατος είναι σχετικά μεγάλος και το σημάδι ποσοστού επιβίωσης είναι υψηλό.
Μόνιμη Γενιά Χρησιμοποιείται για την αποθήκευση στατικών αρχείων, όπως Java, μέθοδοι κ.λπ. Οι μόνιμες γενιές δεν έχουν σημαντικό αντίκτυπο στη συλλογή απορριμμάτων, αλλά ορισμένες εφαρμογές μπορεί να δημιουργήσουν ή να καλέσουν δυναμικά ορισμένες, όπως Αδρανοποίηση κ.λπ., και σε αυτήν την περίπτωση, πρέπει να ρυθμιστεί ένας σχετικά μεγάλος μόνιμος χώρος παραγωγής για την αποθήκευση αυτών των νέων κλάσεων κατά τη διάρκεια του χρόνου εκτέλεσης.
3. GC (Συλλέκτης σκουπιδιών)Συλλέκτες που χρησιμοποιούνται από τους συλλέκτες νέας γενιάς: Serial, PraNew, Parallel Scavenge Συλλέκτες που χρησιμοποιούνται από Συλλέκτες Γήρατος: Serial Old, Parallel Old, CMS
![]()
Σειριακός συλλέκτης (αλγόριθμος αναπαραγωγής) Η νέα γενιά συλλεκτών μονού σπειρώματος, η σήμανση και ο καθαρισμός είναι μονού σπειρώματος, με το πλεονέκτημα ότι είναι απλοί και αποτελεσματικοί.
Σειριακός παλιός συλλέκτης (αλγόριθμος φινιρίσματος ετικέτας) Old Age Single Thread Collector, έκδοση Old Age του Serial Collector.
ParNew collector (αλγόριθμος stop-copy) Ο συλλέκτης νέας γενιάς μπορεί να θεωρηθεί μια έκδοση πολλαπλών νημάτων του σειριακού συλλέκτη, ο οποίος έχει καλύτερη απόδοση από τον σειριακό σε περιβάλλον CPU πολλαπλών πυρήνων.
Παράλληλος συλλέκτης καθαρισμού (αλγόριθμος Stop-Copy) Παράλληλοι συλλέκτες για υψηλή απόδοση και αποτελεσματική χρήση της CPU. Η απόδοση είναι γενικά 99%, και η απόδοση = χρόνος νήματος χρήστη / (χρόνος νήματος χρήστη + χρόνος νήματος GC). Είναι κατάλληλο για σενάρια όπως εφαρμογές παρασκηνίου που δεν απαιτούν αντίστοιχα υψηλή αλληλεπίδραση.
Παράλληλος παλιός συλλέκτης (αλγόριθμος Stop-Copy) Μια παλαιότερη έκδοση του συλλέκτη Parallel Scavenge, ένας παράλληλος συλλέκτης, με προτεραιότητα απόδοσης
Συλλέκτης CMS (Concurrent Mark Sweep) (αλγόριθμος Mark-Clean) Υψηλός συγχρονισμός, χαμηλή παύση, επιδίωξη του συντομότερου χρόνου παύσης ανάκτησης GC, υψηλή χρήση CPU, γρήγορος χρόνος απόκρισης, σύντομος χρόνος παύσης και CPU πολλαπλών πυρήνων που επιδιώκει υψηλό χρόνο απόκρισης
4. Ο μηχανισμός εφαρμογής του GCΔεδομένου ότι το αντικείμενο έχει υποστεί επεξεργασία σε διαφορετικές γενιές, η περιοχή και ο χρόνος συλλογής των σκουπιδιών είναι επίσης διαφορετικοί. Υπάρχουν δύο τύποι GC: Scavenge GC και Full GC.
Καθαρισμός GC Κανονικά, όταν δημιουργείται ένα νέο αντικείμενο και αποτυγχάνει να υποβάλει αίτηση για χώρο στην Εδέμ, θα ενεργοποιηθεί το Scavenge GC, το οποίο θα GC στην περιοχή της Εδέμ, θα καθαρίσει τα μη σωζόμενα αντικείμενα και θα μετακινήσει τα σωζόμενα αντικείμενα στην περιοχή Survivor. Στη συνέχεια, τακτοποιήστε τις δύο ζώνες του Survivor. Το GC με αυτόν τον τρόπο πραγματοποιείται στην περιοχή της Εδέμ της νεότερης γενιάς και δεν επηρεάζει την παλαιότερη γενιά. Επειδή τα περισσότερα αντικείμενα ξεκινούν από την περιοχή της Εδέμ και η περιοχή της Εδέμ δεν εκχωρείται πολύ, το GC της περιοχής της Εδέμ πραγματοποιείται συχνά. Ως εκ τούτου, είναι γενικά απαραίτητο να χρησιμοποιηθούν γρήγοροι και αποτελεσματικοί αλγόριθμοι εδώ για να γίνει το Eden δωρεάν το συντομότερο δυνατό.
Πλήρες GC Οργανώστε ολόκληρο το σωρό, συμπεριλαμβανομένων των Young, Tenured και Perm. Το Full GC είναι πιο αργό από το Scavenge GC επειδή απαιτεί ανακύκλωση ολόκληρου του σωρού, επομένως ο αριθμός των Full GC θα πρέπει να μειωθεί όσο το δυνατόν περισσότερο. Ένα μεγάλο μέρος της διαδικασίας συντονισμού JVM είναι ο συντονισμός του FullGC. Το πλήρες GC μπορεί να προκληθεί από τους ακόλουθους λόγους: 1. Το Tenured γράφεται πλήρες 2. Η περμανάντ είναι γραμμένη πλήρης 3. Το System.gc() εμφανίζεται ως κλήση 4. Η στρατηγική κατανομής domain του Heap αλλάζει δυναμικά μετά το τελευταίο GC
5. Η Java με GC θα έχει επίσης προβλήματα διαρροής μνήμης1. Η χρήση κλάσεων στατικής συλλογής όπως HashMap, Vector κ.λπ. είναι η πιο επιρρεπής σε διαρροή μνήμης και ο κύκλος ζωής αυτών των στατικών μεταβλητών είναι ο ίδιος με αυτόν της εφαρμογής και όλα τα αντικείμενα δεν μπορούν να απελευθερωθούν, επειδή θα εφαρμόζονται πάντα από το Vector και άλλα. Στατικό διάνυσμα v = νέο διάνυσμα(); για (int i = 1; i<100; i++) { Αντικείμενο o = νέο Αντικείμενο(); v.add(o); o = μηδενικό; } Σε αυτό το παράδειγμα, υπάρχει μια αναφορά v για το αντικείμενο Vector και μια αναφορά o για το αντικείμενο Object στη στοίβα κώδικα. Στον βρόχο For, συνεχίζουμε να δημιουργούμε νέα αντικείμενα, στη συνέχεια να τα προσθέτουμε στο αντικείμενο Vector και στη συνέχεια να ακυρώνουμε την αναφορά o. Το ερώτημα είναι, όταν η αναφορά o ακυρώνεται, εάν συμβεί GC, μπορεί το αντικείμενο Object που δημιουργήσαμε να ανακυκλωθεί από το GC; Η απάντηση είναι όχι. Επειδή όταν το GC παρακολουθεί αναφορές στη στοίβα κώδικα, βρίσκει αναφορές v και αν συνεχίσετε να ανιχνεύετε, θα διαπιστώσετε ότι υπάρχουν αναφορές σε αντικείμενα αντικειμένων στο χώρο μνήμης που υποδεικνύεται από αναφορές v. Αυτό σημαίνει ότι παρόλο που η αναφορά o έχει αδειάσει, εξακολουθούν να υπάρχουν άλλες αναφορές στο αντικείμενο Αντικείμενο στις οποίες μπορείτε να έχετε πρόσβαση, επομένως το GC δεν μπορεί να τις ελευθερώσει. Εάν μετά από αυτόν τον βρόχο, το αντικείμενο Object δεν έχει καμία επίδραση στο πρόγραμμα, τότε υποθέτουμε ότι το πρόγραμμα Java έχει διαρροή μνήμης. 2. Διάφορες συνδέσεις, συνδέσεις βάσεων δεδομένων, συνδέσεις δικτύου, συνδέσεις IO κ.λπ. δεν εμφανίζουν την κλήση κοντά στο κλείσιμο και δεν ανακυκλώνονται από το GC, με αποτέλεσμα τη διαρροή μνήμης. 3. Η χρήση ακροατών μπορεί επίσης να προκαλέσει διαρροή μνήμης όταν ο ακροατής δεν διαγράφεται κατά την απελευθέρωση του αντικειμένου.
|