Programmering

Java Tips 105: Mestring av klassestien med JWhich

På et eller annet tidspunkt opplever utviklere frustrasjon når de arbeider med Java-klassestien. Det er ikke alltid klart hvilken klasse klasselasteren vil laste inn, spesielt når programmets klassesti blir oversvømmet med kataloger og filer. I denne artikkelen vil jeg presentere et verktøy som kan vise det absolutte banenavnet til den lastede klassefilen.

Grunnleggende om klassesti

Den virtuelle Java-maskinen (JVM) benytter en klasselaster for å laste klasser som brukes av et program etter behov. De CLASSPATH miljøvariabel forteller klasselaster hvor du finner tredjeparts- og brukerdefinerte klasser. Du kan også spesifisere klassestien per applikasjon med -klassesti JVM kommandolinjeargument, som overstyrer klassestien spesifisert i CLASSPATH miljøvariabel.

Classpath-oppføringer kan være kataloger som inneholder klassefiler for klasser som ikke er i en pakke, pakkens rotkatalog for klasser i en pakke eller arkivfiler (for eksempel .zip- eller .jar-filer) som inneholder klasser. Classpath-oppføringer er kolon-separert på Unix-systemer og semikolon-separert på MS Windows-systemer.

Klasselastere er organisert i et delegasjonshierarki, hvor hver klasselaster har en overordnet klasselaster. Når en klasselaster blir bedt om å finne en klasse, delegerer den først forespørselen til sin overordnede klasselaster før den prøver å finne klassen selv. Systemklasselaster, standard klasselaster fra JDK eller JRE installert på systemet, laster tredjeparts- og brukerdefinerte klasser ved hjelp av CLASSPATH miljøvariabel eller -klassesti JVM kommandolinje argument. Systemklasselaster delegerer til utvidelsesklassen for å laste klasser som bruker Java Extension-mekanismen. Forlengerklasselaster delegerer til bootstrap-klasselaster (pengene stopper her!) For å laste kjernen til JDK-klassene.

Du kan utvikle spesialiserte klasselastere for å tilpasse hvordan JVM dynamisk laster inn klasser. For eksempel bruker de fleste servletmotorer en tilpasset klasselaster for å laste inn servletklasser som er endret i kataloger spesifisert i en tilpasset klassebane dynamisk.

Av spesiell betydning, og mye foruroligelse, vil klasselasteren laste klasser i den rekkefølgen de vises på klassestien. Fra og med den første klassestioppføringen besøker klasselasteren hver spesifiserte katalog eller arkivfil for å prøve å finne klassen som skal lastes inn. Den første klassen den finner med riktig navn er lastet inn, og eventuelle gjenværende klassestioppføringer blir ignorert.

Høres enkelt ut, ikke sant?

Classpath-lureri

Enten de vil innrømme det eller ikke, har både nybegynnere og veteran Java-utviklere på et eller annet tidspunkt (vanligvis i det verste øyeblikket!) Blitt lurt av den belastende klassestien. Etter hvert som antall avhengige tredjeparts- og brukerdefinerte klasser øker for et program, og klassestien blir en dumpingplass for alle tenkelige kataloger og arkivfiler, er det ikke alltid åpenbart hvilken klasse klasselasteren lastes inn først. Dette gjelder spesielt i uheldig tilfelle at klassestien inneholder dupliserte klasseoppføringer. Husk at klasselaster laster inn den første riktig navngitte klassen den finner på klassestien og "skjuler" effektivt alle andre riktig navngitte klasser med lavere prioritet.

Det er altfor lett å bli offer for denne klassebanen. Etter en lang dag med å slave over et varmt tastatur, legger du til en katalog til klassestien i et forsøk på å laste den nyeste og beste versjonen av en klasse inn i applikasjonen, mens du ikke er klar over at en annen versjon av klassen ligger i en katalog høyere prioritet i klassestien. Tok deg!

JWhich: Et enkelt klassestiverktøy

Forrangsproblemet som ligger i en flat baneerklæring er ikke unikt for Java-klassestien. For å finne en løsning på problemet krever bare at du står på skuldrene til legendariske programvaregiganter. Unix-operativsystemet hvilken kommandoen tar et navn og viser stienavnet til filen som ville bli utført hvis navnet ble utstedt som en kommando. Det krysser i hovedsak STI miljøvariabel for å finne den første forekomsten av kommandoen. Det høres ut som et kraftig verktøy for å administrere Java-klassestien også. Inspirert av dette begrepet begynte jeg å skrive et Java-verktøy som kunne ta et Java-klassenavn og vise det absolutte stienavnet til klassefilen som klasselasteren ville laste, som foreskrevet av klassestien.

Følgende eksempel bruk av JHvem viser det absolutte banenavnet for den første forekomsten av com.clarkware.ejb.ShoppingCartBean klasse som skal lastes av klasselaster, som tilfeldigvis er i en katalog:

 > java JWhich com.clarkware.ejb.ShoppingCartBean Class 'com.clarkware.ejb.ShoppingCartBean' funnet i '/home/mclark/classes/com/clarkware/ejb/ShoppingCartBean.class' 

Følgende eksempel bruk av JHvem viser det absolutte banenavnet for den første forekomsten av javax.servlet.http.HttpServlet klasse som skal lastes av klasselaster, som tilfeldigvis er pakket i en arkivfil:

 > java JWhich javax.servlet.http.HttpServlet Class 'javax.servlet.http.HttpServlet' funnet i 'file: /home/mclark/lib/servlet.jar! /javax/servlet/http/HttpServlet.class' 

Hvordan JWhich fungerer

For å entydig bestemme hvilken klasse som skal lastes først i klassestien, må du komme inn i tankene til klasselasteren. Dette er ikke så vanskelig som det høres ut - du bare spør det! Den aktuelle kildekoden for JHvem følger. For fullstendig kildekode, se Ressurser.

1: offentlig klasse JWhich {2: 3: / ** 4: * Skriver ut det absolutte stienavnet til klassefilen 5: * som inneholder det angitte klassenavnet, som foreskrevet 6: * av gjeldende klassesti. 7: * 8: * @param className Navn på klassen. 9: * / 10: offentlig statisk tomrom som (String className) {11: 12: if (! ClassName.startsWith ("/")) {13: className = "/" + className; 14:} 15: className = className.replace ('.', '/'); 16: className = className + ".class"; 17: 18: java.net.URL classUrl = 19: nye JWhich (). GetClass (). GetResource (className); 20: 21: hvis (classUrl! = Null) {22: System.out.println ("\ nClass '" + className + 23: "' funnet i \ n '" + classUrl.getFile () + "'"); 24:} annet {25: System.out.println ("\ nClass '" + className + 26: "' ikke funnet i \ n '" + 27: System.getProperty ("java.class.path") + "' "); 28:} 29:} 30: 31: public static void main (String args []) {32: if (args.length> 0) {33: JWhich.which (args [0]); 34:} annet {35: System.err.println ("Bruk: java JWhich"); 36:} 37:} 38:} 

Først må du massere klassenavnet litt for å få klasselaster-aksept (linje 12-16). Forhåndsbetaling av et "/" til kursnavnet instruerer klasselasteren til å matche kursnavnet ordrett innenfor klassestien, i stedet for å prøve å implisitt forberede pakkenavnet til påkallende klasse. Konverterer hver forekomst av "." til "/" formaterer klassenavnet som et gyldig URL-ressursnavn som kreves av klasselaster.

Deretter blir klasselaster forhørt (linje 18-19) for ressursen som samsvarer med riktig formatert klassenavn. Hver Klasse objektet opprettholder en referanse til ClassLoader objekt som lastet den, så klasselaster som lastet JHvem klassen selv blir avhørt her. De Class.getResource () metoden faktisk delegerer til klasselaster som lastet klassen, returnerer en URL for lesing av klassens filressurs, eller null hvis en klassefilressurs med det angitte klassenavnet ikke ble funnet i den gjeldende klassestien.

Til slutt vises det absolutte banenavnet til klassefilen som inneholder det spesifiserte klassenavnet, hvis det ble funnet i gjeldende klassebane (linje 21-24). Som feilsøkingshjelpemiddel, hvis klassefilen ikke ble funnet i den gjeldende klassestien, får du verdien av java.class.path systemegenskap for å vise gjeldende klassesti (linje 24-28).

Det er lett å forestille seg hvordan denne enkle delen av koden kan påkalles i en Java-servlet ved hjelp av servlets motorens klassebane eller en Enterprise JavaBean (EJB) ved hjelp av EJB-serverens klassebane. Hvis den JHvem klasse ble lastet av den tilpassede klasselasteren i en servletmotor, for eksempel, da ville servletmotorens klasselaster brukes til å finne klasser. Hvis servomotorens klasselaster ikke klarer å finne en klasse, vil den delegere til sin overordnede klasselaster. Generelt når JHvem lastes av en klasselaster, kan den finne alle klassene som er lastet av klasselaster eller en hvilken som helst foreldreklasselaster.

Konklusjon

Hvis nødvendighet er mor til all oppfinnelse, er et verktøy som hjelper til med å administrere Java-klassestien, langvarig. Java-relaterte nyhetsgrupper og adresselister er fulle av spørsmål knyttet til klassestien. Vi må senke barrieren for inngang for nye utviklere, slik at vi alle kan fortsette å arbeide på høyere abstraksjonsnivå. JHvem er et enkelt, men likevel kraftig verktøy som hjelper deg med å mestre Java-klassestien i alle miljøer.

Mike Clark er en uavhengig konsulent for Clarkware Consulting, som spesialiserer seg på Java-basert arkitektur, design og utvikling ved hjelp av J2EE-teknologier. Han fullførte nylig utviklingen og distribusjonen av en business-to-business (B2B) XML-utvekslingsserver og er for tiden konsulent for et prosjekt som bygger et J2EE ytelsesstyringsprodukt.

Lær mer om dette emnet

  • Få full kildekode for denne artikkelen

    //images.techhive.com/downloads/idge/imported/article/jvw/2000/12/jwhich.zip

  • En fullverdig versjon av JWhich, inkludert en klassesti validator, er tilgjengelig på

    //www.clarkware.com/software/jwhich.zip

  • Offisiell dokumentasjon for Sun JDK og hvordan den håndterer klassestien for de forskjellige offisielt støttede plattformene, er tilgjengelig på

    //java.sun.com/j2se/1.3/docs/tooldocs/findingclasses.html

  • For detaljer om hvordan du setter klassestien på Unix- og Windows-plattformer, se "Angi klassestien" på:
  • Unix

    //java.sun.com/j2se/1.3/docs/tooldocs/solaris/classpath.html

  • Windows

    //java.sun.com/j2se/1.3/docs/tooldocs/win32/classpath.html

  • Vis alle forrige Java-tips og send inn dine egne

    //www.javaworld.com/javatips/jw-javatips.index.html

  • For flere Java-triks, abonner gratis på ITworld.com Java-veileder nyhetsbrev

    //www.itworld.com/cgi-bin/subcontent12.cgi

  • Si fra i Java Beginner-diskusjonen, moderert av JavaWorld forfatter Geoff Friesen

    //www.itworld.com/jump/jw-javatip105/forums.itworld.com/webx?14@@.ee6b804/1195!skip=1125

Denne historien, "Java Tip 105: Mastering the classpath with JWhich" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found