Java-kompilering

Fra TermvaktWiki
(Omdirigert fra Java)
Gå til: navigasjon, søk

Denne siden handler om programmeringsspråket Java. Ser du etter rommet med samme navn, se romnavn.

En kort innføring i Java-kompilering.

Innhold

Javainstallasjon på hjemmemaskin

Det er en egen artikkel som forklarer hvordan man kan installere java på hjemmemaskin.

Anbefalte bakgrunnskunnskaper.

Denne veiledningen forutsetter at du kjenner til følgende:

  • Innlogging og vindusbehandling på en linuxmaskin
  • Enkel filbehandling
  • Et tekstredigeringsprogram (Emacs, Vim)

Det kan også være lurt å ha kjennskap til kommandobruk i enten Windows eller Linux (avhengig av hvilket operativsystem du bruker).

Om kompilering

Kompilering er navnet på prosessen som oversetter kildekode til maskinkode. Kildekode betegner formatet som vi skriver programmet i, men maskinkode er en sekvens av enere og nuller som datamaskinen forstår. Denne veiledningen forklarer hvordan man kompilerer Java-programmer. Den tar i tillegg for seg vanlige feilmeldinger ved kompilering og gir forslag på hvordan feilene kan løses.

Teori

Java er et programmeringsspråk som må kompileres, men hovedforskjellen fra tradisjonelle språk er at Java blir kompilert ned til en plattformuavhengig bytekode. Det vil si at den kan kjøres både på Windows, Unix, Linux, Mac OS X, BeOS osv. ved hjelp av en bytekodetolker som kan lese javas bytekode. Under kan man se en figur over hvordan det ser ut.

Obj2.gif

Man ser her at hver enkel prosessorarkitektur og/eller operativsystem har sin egen JVM (men en del arkitekturer og operativsystem har flere JVMer). JVM står for Java Virtual Machine. Det er denne maskinen som oversetter fra Java-bytekode til nuller og ett-tall (0100101010100) som maskinene du sitter på skjønner.

Kompilering og kjøring i praksis

En har ulike måter å kompilere Java-kode, men den vanligste er ved hjelp av programmet javac (det er mulig å kompilere Java direkte til bytekode ved gcj, men det går ut over denne veiledningen). Vi starter med følgende programsnutt:

/** 
 * The HelloWorldApp class implements an application that
 * simply displays "Hello World!" to the standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); //Display the string.
    }
}

Vi skal nå kompilere hele dette programmet. Siden det er et javaprogram det er snakk om, skal helst navnet på fila ha samme navn som den klassen main() ligger i. Filen vi skal kompilere vil da hete HelloWorldApp.java (for enkelhet er det det lurt å lagre filen direkte på hjemmeområdet, hvis du sitter i Windows lagrer du da filen direkte under M:\-disken). For å kompilere filen, åpner du et terminalvindu eller kommandovindu, og beveger deg først til mappen filen ligger i (hvis du lagret filen på hjemmeområdet må du skrive M: i Windows, i Linux trenger du ikke å gjøre noe; hvis filen er lagret et annet sted, bruk kommando cd i Linux og chdir i Windows for å navigere mellom mapper). Deretter kjører du følgende kommando:

javac HelloWorldApp.java

Hvis kompileringen var feilfri (dvs. at ingen feilmelding er kommet opp i terminalvinduet), så er det nå blitt laget en ny fil med navn HelloWorldApp.class. Den nye filen inneholder bytecoden. For å kjøre programmet skriver du følgende inn i terminalvinduet:

java HelloWorldApp

Hvis alt har gått bra, skal teksten "Hello World!" komme ut under linjen java HelloWorldApp.

Kompileringsfeil

I tillegg til at javac-programmet oversetter kildekoden til bytekode, så sjekker den at kildekoden er syntaktisk korrekt (syntaks er regler for hvordan en kan lage setninger el. deler av setninger på et gitt språk). Hvis kildekoden ikke er syntaktisk korrekt vil du få en melding om dette, samt at kompileringen vil stoppe opp. La oss legge inn en feil i HelloWorldApp.java-programmet og se hva som skjer når vi kompilerer.

/** 
 * The HelloWorldApp class implements an application that@]\\
 * simply displays "Hello World!" to the standard output.@]\\
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.println("Hello World!"); //Display the string.
    }   //    +- Her mangler out.
}

Vi skal nå se hva vår kompilator sier da:

bruker@maskin: ~-1> javac HelloWorldApp.java
HelloWorldApp.java:6: cannot resolve symbol
symbol  : method println (java.lang.String)
location: class java.lang.System
    System.println("Hello World!"); //Display the string.
          ^
1 error

Som vi ser sier kompilatoren i fra om at noe er galt. 6-tallet refererer til hvilken linje feilen befinner seg på. Dette er til stor hjelp når man feilsøker programmer. I større programmer eller programmer med veldig mange feil, er det ikke alltid kompilatoren klarer å gi så presise feilmeldinger.

Ubalanserte parenteser (eksempel {{}, {{, {{}{, osv. er alle ubalanserte, fordi det ikke er like mange høyreparenteser som venstreparenteser), samt manglende semikolon på slutten av en linje kan ofte være opphav til flere upresise og misvisende feilmeldinger. Det er derfor en god regel å alltid sjekke dette når man ikke forstår en feil. (Tips: Bruk linjeskift og innrykk på en konsekvent måte som gjør det lett å se slike feil.)

Kjøretidsfeil

Selv om du får kompilert, kan programmet fortsatt inneholde en god del feil som først oppdages ved kjøring. (Dvs. når du gir kommandoen ”java HelloWorldApp”). Disse feilene er ofte mindre informative og dermed vanskeligere å tolke en kompileringsfeil. Vi tar en titt på noen av de vanligste kjøretidsfeilene. La oss ta utgangspunkt i følgende program:

 1: /* The HelloWorldApp class implements an application that
 2:  simply displays "Hello World!" to the standard output.
 3:  */
 4: class HelloWorldApp {
 5:     public static void main(String[] args) {
 6:
 7:         int i = 0;
 8:         String ord[] = new String[4];
 9:
10:         // Fill array with information
11:         ord[0] = new String("Hello ");
12:         ord[1] = new String("World");
13:         ord[2] = "!"; // This is just a shorthand notation 
14:                       // for 'new String "!"; '
15:
16:         // Print the number of characters in ord[1]
17:         System.out.println(ord[1].length());
18:  
19:         // Print the word array
20:         for(; i < 4; i++){
21:             System.out.println(ord[i]); //Display the string.
22:         }
23:     }
24: }


Programmet kompilerer og kjører uten problemer i sin nåværende form:

javac HelloWorldApp.java
java HelloWorldApp

Output:

5
Hello
World
!
null
bruker@maskin: ~-1>

La oss så fremprovosere noen kjøretidsfeil:

ArrayIndexOutOfBoundsException

Ved å endre linje 15 til ”for(;i < 5;i++)” får vi følgende feil:

bruker@maskin: ~-1> javac HelloWorldApp.java
bruker@maskin: ~-1> java HelloWorldApp
5
Hello
World
!
null
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
        at HelloWorldApp.main(HelloWorldApp.java:21)
isolde: ~-1>

Feilen angir at en det er blitt referert til en array med en ugyldig indeksverdi. Indeksen er enten negativ eller større eller lik størrelsen av arrayen. Tallet 4 i feilmeldingen angir den ugyldige indeksverdien og tallet 21 angir hvilken linje i HelloWorldApp.java som fremprovoserte feilen. Vi vet altså at det var ”System.out.println(ord[4]);” som er kilden til feilen, og det er ikke så vanskelig å forstå at ord[4] refererer til en plassering i arrayen som ikke finnes. Arrayen ble via linje 8 gitt en størrelse på 4 elementer, som tilsvarer at ord[0], ord[1], ord[2] og ord[3] er gyldige referanser.(NB! Det er lett å glemme/overse at 4 egentlig refererer til element 5 siden tellingen av elementer i arrayen starter med 0.)

NullPointerException

Ved å endre linje 17 til ”System.out.println(ord[3].length());” får vi følgende feil:

bruker@maskin: ~-1> javac HelloWorldApp.java
bruker@maskin: ~-1>  java HelloWorldApp
Exception in thread "main" java.lang.NullPointerException
        at HelloWorldApp.main(HelloWorldApp.java:17)
bruker@maskin: ~-1>

Feilen angir at det er gjort et forsøk på å bruke ”null” i et tilfelle hvor et objekt var påkrevd. Tallet 17 angir hvilken linje som fremprovoserte feilen. For å forstå denne feilen er det nødvendig å forstå pekere og objekter.

Linje 8 medfører at det blir laget en array med plass til 4 pekere. Det er altså ikke meningen at arrayen skal inneholde selve teksten, noe som enn lett kan tro at skulle være tilfellet ved å se på linjene 11-13. Hvis ikke selve arrayen inneholder tekstene, hva er det da som skjer, hvor blir tekstene av?

Arrayen kan sammenlignes med et kartotek for et bibliotek. Når biblioteket mottar en tekst/bok så legges ikke selve boken inn i kartoteket, men de finner en ledig hylleplass og noterer hyllenummer og seksjon der boken blir plassert på et kartotekkort, og så legges kortet i kartoteket.

Litt forenklet kan vi si at det er det samme som skjer i en PC. Linje 8 medfører i bibliotekverdenen at det opprettes et kartotek med fire blanke kartotekkort. Linjene 11-13 tilsvarer 3 bokleveranser til biblioteket. Når bøkene er registrert og plassert er 3 av de fire kortene i kartoteket fylt ut med plasseringsinformasjon.

Hvis vi trekker samme historie inn i PC-terminologi så skjer følgende: Linje 8 setter av 8 minneplasser hvor hver plass har mulighet for å lagre en adresse til en annen plassering i minne(en peker). Når vi utfører linjen 11 søker vi etter en ledig plass i minne til teksten ”Hello”. (et tekstobjekt.). Når så en stor nok ledig plass er funnet, noteres startadressen til denne ledige plassen i arrayplassen angitt av indeksen [i]. I linje 11 ser vi at startadressen skal lagres i arrayplassen 0. Tilsvarende ting skjer for linje 12 og 13. Når disse linjene er ferdig utført inneholder plassene 0, 1, 2 startadresseinformasjon til henholdsvis tekstene; ”Hello”, ”World” og ”!”. Den siste plassen (3) inneholder fortsatt ingen referanse til et objekt.

Det som mangler nå er å forstå hvorfor linje 17 feiler. I bibliotekverdenen tilsvarer linje 17 at en person kommer inn i biblioteket, og spør etter hvor mange sider boken som er registrert på kartotekkort nr 3 har. Når så bibliotekaren henter kort nr 3 finner han ut at kortet er blankt og må dessverre si at boken mangler.(NullPointerException) Så tilbake til PC terminologien. Linje 17 gir beskjed at datamaskinen skal lese adressen registrert i arrayens plass 3 og deretter gå til denne adressen, hente ut hvor lang teksten var, men som vi husker er det ikke blitt registrert noen adresse i plass 3. Det er altså på grunn av at det ikke eksisterer en peker i plass 3 til et objekt at vi får feilen NullPointerException. Løsningen kunne for eksempel ha vært å legge til følgende linje rett etter linje 13:

ord[3] = new String("Nå er alt i orden");

Ekstern informasjon

Hjemmesiden til Sun sin javac kompilator

Hvordan java programmering fungerer

Man side for java

Man side for javac

Man side for jikes

Personlige verktøy
Navnerom
Varianter
Handlinger
Navigasjon
Kategorier
Programvare
Andre
Translate
Verktøy