Java Hellenic User Group logo

Αρχική Σελίδα
Αγορά Συζήτησης
Κείμενα/Βοηθήματα

Valid CSS!

Πως η εικονική μηχανή της Java φορτώνει τις κλάσεις

Εισαγωγή

Μία Java εφαρμογή μπορεί να αποτελείται από μόνο μία ή πολλές κλάσεις. Αυτές οι κλάσεις φορτώνοντε δυναμικώς, εν ώρα εκτέλεσης της εφαρμογής, όταν η κλάση που ήδη τρέχει αναφέρεται σε αυτές με το όνομά τους. Όλη αυτή η διαδικασία φόρτωσης των κλάσεων γίνεται από τον εκάστοτε Φορτωτή Κλάσεων (Class Loader). Οι φορτωτές κλάσεων είναι και οι ίδιοι κλάσεις γραμμένες σε Java και η δουλειά τους είναι να φορτώνουνε τo bytecode των κλάσεων στην εικονική μηχανή. Χωρίς αυτούς καμία εφαρμογή δεν μπορεί να τρέξει. Μαζί με την κάθε κλάση φορτώνοντε και οι υπερκλάσεις (super classes), οι διεπαφές (interfaces) και ο,τιδήποτε άλλο πάνω στο οποίο βασίζεται η κάθε κλάση.

Προβλήματα και λύσεις

Ωστόσο εδώ υπάρχει ένα πρόβλημα. Οι ίδιοι οι class loaders είναι γραμμένοι σε Java (και αποτελούντε από bytecode), χωρίς αυτούς δεν μπορεί να φορτωθεί και να τρέξει καμία άλλη κλάση και κατ' επέκταση ούτε και οι ίδιοι! Από τη στιγμή που οι class loaders είναι γραμμένοι σε Java τότε εσχάτως όλοι επεκτείνουνε τη java.lang.Object κλάση (όλες οι Java κλάσεις επεκτείνουνε αυτονόητα τη java.lang.Object). Οπότε κανένας class loader δεν μπορεί να τρέξει αν δε φορτωθούν πλήρως  όλες οι υπερκλάσεις του οι οποίες όμως βασίζοντε στον class loader για να φορτωθούνε!

Η λύση είναι φυσικά ότι υπάρχει ένας class loader (που ονομάζεται bootstrap) που αποτελεί τμήμα αυτής καθεαυτής της εικονικής μηχανής και είναι γραμμένος στη γλώσσα που είναι γραμμένη και η εικονική μηχανή. Όταν ο χρήστης χρησιμοποιεί τη java εντολή για να τρέξει ένα πρόγραμμα τότε ο bootstrap φορτώνει τους άλλους class loaders, οι οποίοι με τη σειρά τους προσπαθούνε να φορτώσουνε την κλάση που ακολουθεί και ψάχνουνε να βρούνε τη main μέθοδο.

ClassLoaders

Υπάρχουνε διάφοροι class loaders (μπορούμε να γράψουμε και τους δικούς μας αν το επιθυμούμε) και ο καθένας φορτώνει συγκεκριμένες κλάσεις. Για παράδειγμα άλλος είναι ο class loader που φορτώνει τις κλάσεις που βρίσκοντε στο classpath και άλλος αυτός που φορτώνει τις Applets.

Όπως καταλαβαίνουμε υπάρχει μία ιεραρχία και στους class loaders, ένα «δέντρο» που η ρίζα του είναι ο πρωτογενής class loader (bootstrap) και διακλαδώνεται και σε άλλους. Ο αρχικός class loader φορτώνει κάποιους άλλους και αυτοί με τη σειρά τους φορτώνουνε άλλους κ.ό.κ. Ο πατέρας όλων των class loaders είναι ο bootstrap class loader (ο οποίος φορτώνει τις κλάσεις από το runtime API, δηλαδή το rt.jar) και μετά είναι ο ExtClassLoader (ο οποίος φορτώνει τις κλάσεις από τον /ext υποκατάλογο), μετά έρχεται ο AppClassLoader (φορτώνει τις κλάσεις από το classpath) κ.ό.κ.

Όταν μία κλάση (ας πούμε class A) φορτωθεί από έναν class loader τότε αυτή η κλάση ρωτάει τον ίδιο class loader να φορτώσει και όλες τις εξαρτόμενες κλάσεις (δηλαδή όλες οι κλάσεις που εξαρτούντε από την A). Ο class loader με τη σειρά του πάντα αποστέλνει μήνυμα προς τα πάνω, στο δέντρο των class loaders, για να δει αν κάποιος «γονέας» class loader θέλει να φορτώσει την κλάση πρώτα. Αν κανένας γονέας class loader δεν μπορεί να φορτώσει την κλάση τότε τη φορτώνει ο αρχικός class loader.

Πότε όμως φορτώνοντε οι κλάσεις; Σε ακριβώς δύο περιπτώσεις: όταν η λέξη-κλειδί new χρησιμοποιείται (String s = new String("hello")) και όταν το bytecode κάνει μία στατική αναφορά σε μία κλάση (Class.forName ή System.out). Όταν η εικονική μηχανή ανταμώσει ένα από τα παραπάνω, τότε ο σχετικός class loader θα αναλάβει να φορτώσει την κλάση χρησιμοποιώντας τον κώδικα ClassLoader.loadClass(String className, boolean resolveIt). To classname είναι το όνομα της κλάσης ενώ το resolveIt χρησιμοποιείται για να δείξει αν η κλάση πρέπει να επιλυθεί ή όχι. Μπορούμε να σκεφτούμε την επίλυση μίας κλάσης ώς τη διαδικασία φόρτωσής της για να τρέξει (δηλαδή φόρτωση και όλων των από αυτή εξαρτόμενων κλάσεων). Μία κλάση που δεν πρέπει να επιλυθεί μπορεί απλώς να φορτωθεί στη μνήμη μόνο και μόνο για να δούμε αν υπάρχει ή για να βρούμε την υπερκλάση της για παράδειγμα.

Aποστολόπουλος Πάρις
Κωνσταντινίδης Πάνος


  Get Java Now!