java:classpath

Η μεταβλητή περιβάλλοντος CLASSPATH

Ως CLASSPATH ορίζεται το σύνολο των καταλόγων (directories) του συστήματος στα οποία βρίσκονται μεταγλωττισμένες κλάσεις (δηλ .class αρχεία) και οι οποίες είναι απαραίτητες για την μεταγλώττιση ή για τη εκτέλεση ενός προγράμματος Java. Με άλλα λόγια το CLASSPATH για κάθε Java πρόγραμμα δείχνει στο σύνολο των βιβλιοθηκών που απαιτούνται.

Όλα τα λειτουργικά συστήματα διαθέτουν την μεταβλητή PATH, όπου προσδιορίζονται οι κατάλογοι του συστήματος οι οποίοι περιέχουν εκτελέσιμα αρχεία συστήματος. Σε αναλογία με την μεταβλητή PATH, η μεταβλητή CLASSPATH προσδιορίζει του καταλόγους ή τα αρχεία τύπου .jar που είναι απαραίτητα για τη εκτέλεση ή την μεταγλώττιση ενός πρόγράμματος. Η μεταβλητή CLASSPATH αποτελεί μεταβλητή του συστήματος, την οποία τα εργαλεία της Java ελέγχουν για ύπαρξη πιθανών βιβλιοθηκών.

Αλλάζοντας μόνιμα την μεταβλητή CLASSPATH

Στα πλαίσια του μαθήματος μας ΔΕΝ θα χρειαστεί να αλλάξετε μόνιμα την μεταβλητή CLASSPATH. Εάν επιθυμείτε αλλαγή της μεταβλητής CLASSPATΗ μπορείτε να το κάνετε με την βοήθεια των παρακάτω συνδέσμων.

Αλλάζοντας προσωρινά την μεταβλητή CLASSPATH

Στις περισσότερες περιπτώσεις αυτό που θα σας ζητηθεί είναι ο προσωρινός ορισμός του περιεχομένου της μεταβλητής CLASSPATH για τις ανάγκες ενός προγράμματος. Για να μεταγλωττίσετε ή για να τρέξετε το πρόγραμμα σας συχνά θα χρειαστείτε άλλες κλάσεις τις οποίες έχετε μεταγλωττίσει ή βιβλιοθήκες τρίτων τις οποίες χρησιμοποιείτε στα προγράμματα σας. Για να ορίσετε επομένως τα PATHs των κλάσεων ή των βιβλιθηκών αυτών θα χρειαστεί να προσδιορίσετε τις κλάσεις ή τις βιβλιοθήκες αυτές. Αυτό το κάνετε κατά την μεταγλώττιση ή κατά την εκτέλεση ενός προγράμματος μέσω του flag -classpath ή -cp.

Όταν ορίζετε την μεταβλητή CLASSPATH μέσω της επιλογής (flag) -classpath ή -cp κάνετε overwrite την μεταβλητή περιβάλλοντος CLASSPATH που πιθανόν έχετε ορίσει προηγούμενα.

Παραδείγματα χρήσης CLASSPATH

Χρήση Classpath - Παράδειγμα 1ο

Προσοχή: Η μεταβλητή CLASSPATH δείχνει κάθε φορά όχι που βρίσκονται τα τελικά αρχεία *.class για κάθε κλάση, αλλά που θα πρέπει να ψάξει ο compiler ή το JRE για αρχεία *.class.

Θα εξηγήσουμε αυτή την λεπτή διαφορά με ένα παράδειγμα. Ας υποθέσουμε ότι έχετε τις κλάσεις

my.package1.Class1
my.package2.Class2

που βρίσκονται στον κατάλογο myProject/src/ δηλαδή

myProject/src/my/package1/Class1.java
myProject/src/my/package2/Class2.java

οι οποίες μεταγλωττίζονται μέσα στον κατάλογο myProject/build/classes/ με μία δήλωση της μορφής:

cd path/to/dir/myProject
javac -d build/classes/ src/my/package1/Class1.java
javac -d build/classes/ src/my/package1/Class2.java

, δηλαδή έχουμε

myProject/build/classes/my/package1/Class1.class
myProject/build/classes/my/package2/Class2.class

Αν θέλετε να μεταγλωττίσετε ή να εκτελέσετε ένα πρόγραμμα το οποίο χρησιμοποιεί τις παραπάνω μεταγλωττισμένες κλάσεις θα πρέπει να δηλώσετε ως classpath τον κατάλογο myProject/build/classes/.

δηλαδή

javac -cp path/to/dir/myProject/build/classes/ JavaClassToCompileAndRun.java

Από εκεί και κάτω, εφόσον ο compiler γνωρίζει το πλήρες όνομα της κλάσης (<package name> + <class name>) αναζητά στο αντίστοιχο path την κλάση που χρειάζεται κάθε φορά.

Έτσι αν ο compiler ή το JRE χρειάζεται την κλάση my.package1.Class1 τότε στο classpath που έχετε ορίσει θα ψάξει για την κλάση με συνολικό path myProject/build/classes/my/package1/Class1.class.

Χρήση Classpath - Παράδειγμα 2ο

Κατεβάστε το παράδειγμα classpath_usage_ex2.tgz.

Aς υποθέσουμε ότι θέλετε να μεταγλωττίσετε την κλάση MyTestClass.java η οποία απαιτεί τις κλάσεις my.library.Cone.java και my.library.Cylinder.java, δηλαδή τις κλάσεις Cone και Cylinder που ανήκουν στο package my.library. Ας υποθέσουμε επίσης ότι στο λειτουργικό σύστημα Linux το path των παραπάνω μεταγλωττισμένων κλάσεων βρίσκεται στον παρακάτω κατάλογο

/path/to/dir/classpath_usage_ex1/build/classes/my/library/Cone.class
/path/to/dir/classpath_usage_ex1/build/classes/my/library/Cylinder.class

Επίσης, το πακέτο my.library μετά την μεταγλώττιση όλων των κλάσεων που ανήκουν σε αυτό συμπιέζεται στο αρχείο my-library.jar που βρίσκεται στον κατάλογο

/path/to/dir/classpath_usage_ex1/build/jar/my-library.jar

Χρήση dir classpath

Για να μεταγλωττίσετε την κλάση του παραπάνω παραδείγματος αρκεί να γράψετε.

javac MyTestClass.java -cp /path/to/dir/classpath_usage_ex1/build/classes/

Χρήση jar classpath

Εάν θέλετε να ορίσετε στο CLASSPATH ένα jar αρχείο που περιέχει κλάσεις που απαιτούνται κατά την μεταγλώττιση ή την εκτέλεση του προγράμματος σας τότε ορίζετε στο CLASSPATH το jar αρχείο. Για να μεταγλωττίσετε την κλάση του παραπάνω παραδείγματος αρκεί να γράψετε.

javac MyTestClass.java -cp /path/to/dir/classpath_usage_ex1/build/jar/my-library.jar

Παρατηρήστε ότι ορίζουμε το jar αρχείο και όχι τον κατάλογο στον οποίο περιέχεται. Στο παραπάνω παράδειγμα χρησιμοποιούμε απόλυτα paths για τον ορισμό του CLASSPATH. Φυσικά μπορείτε να χρησιμοποιείται και σχετικά paths, όπως παρακάτω

Υποθέτωντας ότι βρίσκεστε στον κατάλογο /home/username/Java/test/ θα γράφατε.

javac MyTestClass.java -cp build/jar/my-library.jar

Χρήση πολλαπλών classpaths

Εάν θέλετε να ορίσετε στο CLASSPATH πολλαπλά jar αρχεία ή directories, τότε μπορείτε να το κάνετε ακολουθώντας τους παραπάνω κανόνες και χωρίζοντας τις εγγραφές με τον χαρακτήρα ':' στο Linux ή με τον χαρακτήρα ';' στο λειτουργικό σύστημα Windows.

Αν για παράδειγμα, στο παραπάνω παράδειγμα εκτός από τις παραπάνω δύο κλάσεις χρειάζεστε και την κλάση gr.ntua.ece.java.common-libs.SinglyNodeList που βρίσκεται στο dir

/home/username/CE325/other_libs/ntua-common-libs.jar (Linux) ή
C:\Users\username\CE325\other_libs\ntua-common-libs.jar (Windows)

τότε για την μεταγλώττιση θα πρέπει να γράψετε

για Linux

javac MyTestClass.java -cp /home/username/CE325/my_projects/homework2/build/classes:/home/username/CE325/other_libs/ntua-common-libs.jar

για Windows

javac MyTestClass.java -cp C:\Users\username\CE325\my_projects\homework2\build\classes;C:\Users\username\CE325\other_libs\ntua-common-libs.jar

Αν δεν έχετε ορίσει την μεταβλητή περιβάλλοντος CLASSPATH και παράλληλα δεν έχετε ορίσει το CLASSPATH μέσω της επιλογής -cp ή –classpath τότε η default τιμή είναι το τρέχον directory. Εάν ορίσετε μία ή περισσότερες τιμές μέσω της επιλογής -cp ή –classpath, τότε το τρέχον directory δεν είναι στη λίστα των καταλόγων του classpath. Εάν το χρειάζεστε θα πρέπει να το προσθέσετε με μία δήλωση της μορφής ./, όπως παρακάτω για λειτουργικό σύστημα Linux.

javac MyTestClass.java -cp /home/username/CE325/my_projects/homework2/build/classes:/home/username/CE325/other_libs/ntua-common-libs.jar:./

Μεταγλώττιση κλάσεων με χρήση της επιλογής --sourcepath

Συχνά θέλετε να μεταγλωττίσετε κώδικα που έχετε φτιάξει και αποτελείται από ένα σύνολο κλάσεων οι οποίες αλληλοεξαρτώνται μεταξύ τους. Σε αυτή την περίπτωση η επιλογή –classpath δεν έχει ιδιαίτερο νόημα, καθώς αρχικά δεν υπάρχουν μεταγλωττισμένες κλάσεις που μπορείτε να χρησιμοποιήσετε. Ο java compiler μπορεί να λάβει υπόψη του εκτός από μεταγλωττισμένες κλάσεις και αρχεία πηγαίου κώδικα προς μεταγλώττιση. Έτσι εάν μία κλάση την οποία χρειάζεστε δεν είναι μεταγλωττισμένη μπορείτε να το κάνετε δείχνοντας στα αρχεία πηγαίου κώδικα και όχι στα μεταγλωττισμένα αρχεία.

Σε αυτή την περίπτωση καλείστε να κάνετε χρήση της επιλογής –sourcepath, η οποία δείχνει σε μη μεταγλωττισμένα αρχεία. Για παράδειγμα, ας υποθέσουμε ότι το αρχείο

gr/uth/inf/ce325/homework2/Cylinder.java

που ανήκει στο package gr.uth.inf.ce325.homework2 και βρίσκεται μέσα στον κατάλογο

/home/username/CE325/my_projects/homework2/src/gr/uth/inf/ce325/homework2/Cylinder.java

απαιτεί για την μεταγλώττιση του την κλάση

gr.uth.inf.ce325.homework2.Circle

η οποία δεν είναι ακόμη μεταγλωττισμένη. Η μεταγλώττιση του συγκεκριμένου αρχείου μπορεί να γίνει ως εξής:

cd /home/username/CE325/my_projects/homework2/src/
javac gr/uth/inf/ce325/homework2/Cylinder.java -sourcepath ./

Μέσω της επιλογής –sourcepath ο μεταγλωττιστής έχει πρόσβαση στο αρχείο πηγαίου κώδικα Circle.java που βρίσκεται στον κατάλογο

/home/username/CE325/my_projects/homework2/src/gr/uth/inf/ce325/homework2/Circle.java

Παράδειγμα μεταγλώττισης και εκτέλεσης

Δείτε το παρακάτω παράδειγμα μεταγλώττισης και εκτέλεσης του παρακάτω κώδικα lec10-packages-classpath-demo.zip για λειτουργικό σύστημα Windows (προσαρμόστε ανάλογα για λειτουργικό σύστημα Linux). Αφού πάτε μέσα στον κατάλογο lec10-packages-classpath-demo καλείστε να γράψετε τα εξής:

Μεταγλώττιση επιμέρους αρχείων

cd src
javac gr\uth\inf\_2d_shapes\Point.java -d ..\build\classes\
javac gr\uth\inf\_2d_shapes\Rectangle.java -sourcepath . -d ..\build\classes\
javac gr\uth\inf\_3d_shapes\Cuboid.java -sourcepath . -d ..\build\classes\
cd ..
javac ClasspathDemo.java -sourcepath src\

Δημιουργία jar αρχείου

cd build\jar 
jar cvf shapes.jar -C ..\classes\ .

Εκτέλεση

cd ..\..  // στον κατάλογο lec10-packages-classpath-demo
java -cp build\classes;. ClasspathDemo
ή με χρήση του jar αρχείου
java -cp build\jar\shapes.jar;. ClasspathDemo

Εναλλακτικά χρησιμοποιήστε το αρχείο build.xml που επισυνάπτεται για να αυτοματοποιήσετε την παραπάνω διαδικασία με το πρόγραμμα Apache Ant. Περισσότερα για την μεταγλώττιση με την βοήθεια του Apache Ant μπορείτε να βρείτε στην ενότητα που ακολουθεί.

java/classpath.txt · Last modified: 2016/02/26 11:15 (external edit)