Java Language
Het Java-commando - 'java' en 'javaw'
Zoeken…
Syntaxis
java [ <opt> ... ] <class-name> [ <argument> ... ]
java [ <opt> ... ] -jar <jar-file-pathname> [ <argument> ... ]
Opmerkingen
De java
opdracht wordt gebruikt voor het uitvoeren van een Java-toepassing vanaf de opdrachtregel. Het is beschikbaar als onderdeel van elke Java SE JRE of JDK.
Op Windows-systemen zijn er twee varianten van het java
commando:
- De
java
variant start de toepassing in een nieuw consolevenster. - De
javaw
start de toepassing zonder een nieuw consolevenster te maken.
Op andere systemen (bijv. Linux, Mac OSX, UNIX) wordt alleen het java
commando gegeven en wordt geen nieuw consolevenster geopend.
Het symbool <opt>
in de syntaxis geeft een optie aan op de opdrachtregel van java
. De onderwerpen "Java-opties" en "Opties voor heap- en stapelgrootte" hebben betrekking op de meest gebruikte opties. Anderen worden behandeld in het onderwerp JVM-vlaggen .
Een uitvoerbaar JAR-bestand uitvoeren
Uitvoerbare JAR-bestanden zijn de eenvoudigste manier om Java-code samen te voegen in een enkel bestand dat kan worden uitgevoerd. * (Noot redactie: het maken van JAR-bestanden moet in een afzonderlijk onderwerp worden behandeld.) *
Ervan uitgaande dat u een uitvoerbaar JAR-bestand met padnaam <jar-path>
, zou u het als volgt moeten kunnen uitvoeren:
java -jar <jar-path>
Als de opdracht opdrachtregelargumenten vereist, voegt u deze toe na het <jar-path>
. Bijvoorbeeld:
java -jar <jar-path> arg1 arg2 arg3
Als u extra JVM-opties op de java
opdrachtregel moet -jar
, moeten deze vóór de optie -jar
. Merk op dat een -cp
/ -classpath
optie wordt genegeerd als u -jar
. Het klassenpad van de toepassing wordt bepaald door het JAR-bestandsmanifest.
Java-applicaties uitvoeren via een "hoofdklasse"
Wanneer een toepassing niet als uitvoerbare JAR is verpakt, moet u de naam van een entry-point-klasse java
op de java
opdrachtregel.
De klasse HelloWorld uitvoeren
Het voorbeeld "HelloWorld" wordt beschreven in Een nieuw Java-programma maken . Het bestaat uit een enkele klasse met de naam HelloWorld
die voldoet aan de vereisten voor een instappunt.
Ervan uitgaande dat het (gecompileerde) bestand "HelloWorld.class" zich in de huidige map bevindt, kan het als volgt worden gestart:
java HelloWorld
Enkele belangrijke dingen om op te merken zijn:
- We moeten de naam van de klasse opgeven: niet de padnaam voor het bestand ".class" of het bestand ".java".
- Als de klasse in een pakket wordt gedeclareerd (zoals de meeste Java-klassen zijn), moet de klassenaam die we aan het
java
commando leveren de volledige klassenaam zijn. AlsSomeClass
bijvoorbeeld wordt gedeclareerd in het pakketcom.example
, is de volledigecom.example.SomeClass
.
Een klassenpad opgeven
Tenzij we de syntaxis van de java -jar
opdracht gebruiken, zoekt de java
opdracht naar de klasse die moet worden geladen door het klassepad te doorzoeken; zie The Classpath . De bovenstaande opdracht is afhankelijk van het standaardklassepad (of inclusief) de huidige map. We kunnen dit explicieter maken door het te gebruiken classpath op te geven met de optie -cp
.
java -cp . HelloWorld
Dit zegt dat de huidige directory (waarnaar "." Verwijst) het enige item in het classpath wordt.
De -cp
is een optie die wordt verwerkt door het java
commando. Alle opties die bedoeld zijn voor het java
commando moeten vóór de klassennaam staan. Alles wat na de les zal worden behandeld als een command line argument voor de Java-toepassing, en zal worden doorgegeven aan de toepassing in de String[]
die aan de doorgegeven main
methode.
(Als er geen -cp
optie is opgegeven, gebruikt de java
het classpath dat wordt opgegeven door de omgevingsvariabele CLASSPATH
. Als die variabele niet is ingesteld of leeg is, gebruikt java
"." Als standaard classpath.)
Ingangspunt klassen
Een Java entry-point klasse heeft een main
methode met de volgende handtekening en modifiers:
public static void main(String[] args)
Sidenote: vanwege de manier waarop arrays werken, kan dit ook zijn
(String args[])
Wanneer het java
commando de virtuele machine start, laadt het de opgegeven entry-point klassen en probeert het main
te vinden. Als dit lukt, worden de argumenten van de opdrachtregel geconverteerd naar Java String
objecten en verzameld in een array. Als main
op deze manier wordt aangeroepen, is de array niet null
en bevat deze geen null
items.
Een geldige entry-point class-methode moet het volgende doen:
- Worden genoemd
main
(hoofdlettergevoelig) - Wees
public
enstatic
- Voer een
void
retourtype in - Heb een enkel argument met een array
String[]
. Het argument moet aanwezig zijn en niet meer dan één argument is toegestaan. - Wees generiek: typeparameters zijn niet toegestaan.
- Heb een niet-generieke insluitende klasse op het hoogste niveau (niet genest of innerlijk)
Het is gebruikelijk om de klasse public
te verklaren, maar dit is niet strikt noodzakelijk. Java 5 verder, de main
kunnen methode argumenttype zijn een String
varargs plaats van een tekenreeksarray. main
kan optioneel uitzonderingen genereren, en de parameter kan alles worden genoemd, maar conventioneel is het args
.
JavaFX entry-punten
Vanaf Java 8 kan het java
commando ook rechtstreeks een JavaFX-toepassing starten. JavaFX is gedocumenteerd in de JavaFX- tag, maar een JavaFX entry-point moet het volgende doen:
- Verleng
javafx.application.Application
- Wees
public
en nietabstract
- Niet generiek of genest zijn
- Heb een expliciete of impliciete
public
no-args constructor
Problemen met de opdracht 'java' oplossen
Dit voorbeeld behandelt veelvoorkomende fouten bij het gebruik van de opdracht 'java'.
"Opdracht niet gevonden"
Als u een foutmelding krijgt zoals:
java: command not found
wanneer u probeert het java
commando uit te voeren, betekent dit dat er geen java
commando op het opdrachtzoekpad van uw shell staat. De oorzaak kan zijn:
- je hebt helemaal geen Java JRE of JDK geïnstalleerd,
- u hebt de omgevingsvariabele
PATH
niet (correct) bijgewerkt in uw shell-initialisatiebestand, of - u hebt niet het relevante initialisatiebestand in de huidige shell "gevonden".
Raadpleeg "Java installeren" voor de stappen die u moet nemen.
"Kon hoofdklasse niet vinden of laden"
Dit foutbericht wordt uitgevoerd door het java
commando als het de opgegeven entry-class niet heeft kunnen vinden / laden. Over het algemeen zijn er drie brede redenen waarom dit kan gebeuren:
- U hebt een ingangspuntklasse opgegeven die niet bestaat.
- De klasse bestaat, maar u hebt deze onjuist opgegeven.
- De klasse bestaat en u hebt deze correct opgegeven, maar Java kan deze niet vinden omdat het classpath onjuist is.
Hier is een procedure om het probleem te diagnosticeren en op te lossen:
Ontdek de volledige naam van de entry-pointklasse.
- Als u broncode voor een klasse hebt, bestaat de volledige naam uit de pakketnaam en de eenvoudige klassenaam. De instantie van de klasse "Main" wordt gedeclareerd in het pakket "com.example.myapp" en de volledige naam is "com.example.myapp.Main".
- Als u een gecompileerd klassenbestand hebt, kunt u de
javap
vinden doorjavap
erop uit te voeren. - Als het klassenbestand zich in een map bevindt, kunt u de volledige klassenaam afleiden uit de mapnamen.
- Als het klassenbestand zich in een JAR- of ZIP-bestand bevindt, kunt u de volledige klassenaam afleiden uit het bestandspad in het JAR- of ZIP-bestand.
Bekijk het foutbericht van het
java
commando. Het bericht moet eindigen met de volledige klassennaam diejava
probeert te gebruiken.- Controleer of deze exact overeenkomt met de volledige klassenaam voor de ingangspuntklasse.
- Het moet niet eindigen met ".java" of ".class".
- Het mag geen schuine strepen of andere tekens bevatten die niet legaal zijn in een Java-ID 1 .
- De behuizing van de naam moet exact overeenkomen met de volledige klassenaam.
Als u de juiste klassenaam gebruikt, moet u ervoor zorgen dat de klasse zich op het klassenpad bevindt:
- Bereken de padnaam waaraan de klassenaam is toegewezen; zie Klasnamen toewijzen aan padnamen
- Bedenk wat het classpath is; zie dit voorbeeld: verschillende manieren om het klassenpad op te geven
- Bekijk elk van de JAR- en ZIP-bestanden op het klassenpad om te zien of deze een klasse bevatten met de vereiste padnaam.
- Kijk naar elke map om te zien of de padnaam wordt omgezet in een bestand in de map.
Als het probleem niet is gevonden door het classpath handmatig te controleren, kunt u de opties -Xdiag
en -XshowSettings
. De eerste lijst toont alle klassen die zijn geladen en de laatste drukt instellingen af die het effectieve klassenpad voor de JVM bevatten.
Ten slotte zijn er enkele obscure oorzaken voor dit probleem:
- Een uitvoerbaar JAR-bestand met een kenmerk
Main-Class
dat een klasse aangeeft die niet bestaat. - Een uitvoerbaar JAR-bestand met een onjuist
Class-Path
kenmerk. - Als je rotzooi op 2 de opties voor de classname, de
java
kan commando proberen om één van hen te interpreteren als de classname. - Als iemand regels in Java-stijl heeft genegeerd en pakket- of klasse-ID's heeft gebruikt die alleen in hoofdletters en kleine letters verschillen, en u op een platform werkt dat hoofdletters en kleine letters in bestandsnamen beschouwt als niet-significant.
- Problemen met homoglyphs in klassennamen in de code of op de opdrachtregel.
"Hoofdmethode niet gevonden in klasse <naam>"
Dit probleem treedt op wanneer het java
commando de klasse die u heeft genomineerd kan vinden en laden, maar vervolgens geen ingangspuntmethode kan vinden.
Er zijn drie mogelijke verklaringen:
- Als u probeert een uitvoerbaar JAR-bestand uit te voeren, heeft het JAR-manifest een onjuist "Main-Class" -kenmerk dat een klasse opgeeft die geen geldige entry point-klasse is.
- U hebt het
java
commando een klasse verteld die geen ingangspuntklasse is. - De ingangspuntklasse is onjuist; zie Invoerpuntklassen voor meer informatie.
Andere bronnen
- Wat betekent "Kon hoofdklasse niet vinden of laden"?
- http://docs.oracle.com/javase/tutorial/getStarted/problems/index.html
1 - Vanaf Java 8 en later zal het java
commando een scheidingsteken voor bestandsnamen ("/" of "") nuttig toewijzen aan een punt ("."). Dit gedrag is echter niet gedocumenteerd in de handleidingpagina's.
2 - Een echt obscuur geval is als u een opdracht uit een opgemaakt document kopieert en plakt waarbij de teksteditor een "lang koppelteken" heeft gebruikt in plaats van een gewoon koppelteken.
Een Java-toepassing uitvoeren met bibliotheekafhankelijkheden
Dit is een voortzetting van de voorbeelden "hoofdklasse" en "uitvoerbare JAR" .
Typische Java-applicaties bestaan uit een applicatiespecifieke code en verschillende herbruikbare bibliotheekcode die u hebt geïmplementeerd of die door derden is geïmplementeerd. Deze laatste worden meestal bibliotheekafhankelijkheid genoemd en worden meestal verpakt als JAR-bestanden.
Java is een dynamisch gebonden taal. Wanneer u een Java-toepassing met bibliotheekafhankelijkheden uitvoert, moet de JVM weten waar de afhankelijkheden zijn, zodat klassen naar wens kunnen worden geladen. In grote lijnen zijn er twee manieren om hiermee om te gaan:
De applicatie en zijn afhankelijkheden kunnen opnieuw worden verpakt in een enkel JAR-bestand dat alle vereiste klassen en bronnen bevat.
De JVM kan via het runtime classpath worden verteld waar de afhankelijke JAR-bestanden kunnen worden gevonden.
Voor een uitvoerbaar JAR-bestand wordt het runtime-classpath gespecificeerd door het manifestkenmerk "Class-Path". (Noot voor de redactie: dit moet worden beschreven in een afzonderlijk onderwerp bij de opdracht jar
.) Anders moet het runtime classpath worden opgegeven met de optie -cp
of met de omgevingsvariabele CLASSPATH
.
Stel bijvoorbeeld dat we een Java-toepassing hebben in het bestand "myApp.jar" waarvan de toegangspuntklasse com.example.MyApp
. Stel ook dat de toepassing afhankelijk is van JAR-bestanden van de bibliotheek "lib / library1.jar" en "lib / library2.jar". We kunnen de applicatie als volgt starten met de opdracht java
op een opdrachtregel:
$ # Alternative 1 (preferred)
$ java -cp myApp.jar:lib/library1.jar:lib/library2.jar com.example.MyApp
$ # Alternative 2
$ export CLASSPATH=myApp.jar:lib/library1.jar:lib/library2.jar
$ java com.example.MyApp
(In Windows gebruikt u ;
plaats van :
als scheidingsteken voor het klassenpad en stelt u de (lokale) variabele CLASSPATH
met behulp van set
plaats van export
.)
Hoewel een Java-ontwikkelaar zich daar prettig bij zou voelen, is het niet "gebruiksvriendelijk". Het is dus gebruikelijk om een eenvoudig shellscript (of Windows-batchbestand) te schrijven om de details te verbergen die de gebruiker niet hoeft te weten. Als u bijvoorbeeld het volgende shellscript in een bestand met de naam "myApp" plaatst, het uitvoerbaar maakt en in een map op het opdrachtzoekpad plaatst:
#!/bin/bash
# The 'myApp' wrapper script
export DIR=/usr/libexec/myApp
export CLASSPATH=$DIR/myApp.jar:$DIR/lib/library1.jar:$DIR/lib/library2.jar
java com.example.MyApp
dan zou je het als volgt kunnen uitvoeren:
$ myApp arg1 arg2 ...
Alle argumenten op de opdrachtregel worden doorgegeven aan de Java-toepassing via de uitbreiding "$@"
. (U kunt iets soortgelijks doen met een Windows-batchbestand, hoewel de syntaxis anders is.)
Spaties en andere speciale tekens in argumenten
Allereerst is het probleem van het omgaan met spaties in argumenten GEEN Java-probleem. Het is eerder een probleem dat moet worden opgelost door de opdrachtshell die u gebruikt wanneer u een Java-programma uitvoert.
Laten we als voorbeeld eens aannemen dat we het volgende eenvoudige programma hebben dat de grootte van een bestand afdrukt:
import java.io.File;
public class PrintFileSizes {
public static void main(String[] args) {
for (String name: args) {
File file = new File(name);
System.out.println("Size of '" + file + "' is " + file.size());
}
}
}
Stel nu dat we de grootte van een bestand willen afdrukken waarvan de padnaam spaties bevat; bijv. /home/steve/Test File.txt
. Als we de opdracht als volgt uitvoeren:
$ java PrintFileSizes /home/steve/Test File.txt
de shell weet niet dat /home/steve/Test File.txt
eigenlijk één padnaam is. In plaats daarvan geeft het 2 afzonderlijke argumenten door aan de Java-toepassing, die zal proberen hun respectieve bestandsgrootten te vinden, en mislukken omdat bestanden met die paden (waarschijnlijk) niet bestaan.
Oplossingen met behulp van een POSIX-shell
POSIX-shells bevatten zowel sh
als derivaten zoals bash
en ksh
. Als u een van deze shells gebruikt, kunt u het probleem oplossen door het argument te citeren .
$ java PrintFileSizes "/home/steve/Test File.txt"
De dubbele aanhalingstekens rond de padnaam vertellen de shell dat deze als een enkel argument moet worden doorgegeven. De aanhalingstekens worden verwijderd wanneer dit gebeurt. Er zijn een paar andere manieren om dit te doen:
$ java PrintFileSizes '/home/steve/Test File.txt'
Enkele (rechte) aanhalingstekens worden behandeld als dubbele aanhalingstekens, behalve dat ze ook verschillende uitbreidingen in het argument onderdrukken.
$ java PrintFileSizes /home/steve/Test\ File.txt
Een backslash ontsnapt aan de volgende ruimte en zorgt ervoor dat deze niet wordt geïnterpreteerd als argumentscheidingsteken.
Voor meer uitgebreide documentatie, inclusief beschrijvingen van hoe om te gaan met andere speciale karakters in argumenten, verwijzen wij u naar het citaatonderwerp in de Bash- documentatie.
Oplossing voor Windows
Het fundamentele probleem voor Windows is dat op OS-niveau de argumenten als één string ( bron ) aan een onderliggend proces worden doorgegeven. Dit betekent dat de uiteindelijke verantwoordelijkheid voor het parseren (of opnieuw parseren) van de opdrachtregel op elk programma of op de runtime-bibliotheken valt. Er is veel inconsistentie.
In het geval van Java, om een lang verhaal kort te maken:
U kunt dubbele aanhalingstekens om een argument in een
java
commando plaatsen, en daarmee kunt u argumenten met spaties doorgeven.Blijkbaar ontleedt het
java
commando zelf de commandostring en krijgt het min of meer gelijkWanneer u dit echter probeert te combineren met het gebruik van
SET
en variabele substitutie in een batchbestand, wordt het erg ingewikkeld of dubbele aanhalingstekens worden verwijderd.De
cmd.exe
shell heeft blijkbaar andere ontsnappingsmechanismen; bijv. dubbele aanhalingstekens en^
escapes gebruiken.
Raadpleeg de documentatie over het batchbestand voor meer informatie.
Java-opties
Het java
commando ondersteunt een breed scala aan opties:
Alle opties beginnen met een enkel koppelteken of minteken (
-
): de GNU / Linux-conventie van het gebruik van--
voor "lange" opties wordt niet ondersteund.Opties moeten worden weergegeven vóór het argument
<classname>
of het argument-jar <jarfile>
om te worden herkend. Alle argumenten erna worden behandeld als argumenten die worden doorgegeven aan de Java-app die wordt uitgevoerd.Opties die niet beginnen met
-X
of-XX
zijn standaardopties. U kunt op alle Java-implementaties 1 vertrouwen om elke standaardoptie te ondersteunen.Opties die beginnen met
-X
zijn niet-standaardopties en kunnen worden teruggetrokken van de ene Java-versie naar de volgende.Opties die beginnen met
-XX
zijn geavanceerde opties en kunnen ook worden ingetrokken.
Systeemeigenschappen instellen met -D
De -D<property>=<value>
optie wordt gebruikt om een onroerend goed in het systeem in te stellen Properties
object. Deze parameter kan worden herhaald om verschillende eigenschappen in te stellen.
Geheugen-, stapel- en afvalverzamelaaropties
De belangrijkste opties voor het regelen van de heap- en stapelgroottes zijn gedocumenteerd in De heap-, PermGen- en stapelgroottes instellen . (Noot voor de redactie: Garbage Collector-opties moeten in hetzelfde onderwerp worden beschreven.)
Beweringen in- en uitschakelen
De -ea
en -da
opties respectievelijk in- en uitschakelen Java assert
controleren:
- Alle beweringen worden standaard uitgeschakeld.
- Met de optie
-ea
kunnen alle beweringen worden gecontroleerd - De
-ea:<packagename>...
maakt het mogelijk beweringen in een pakket en alle subpakketten te controleren . - De
-ea:<classname>...
maakt het mogelijk beweringen in een klasse te controleren. - De optie
-da
schakelt het controleren van alle beweringen uit - De
-da:<packagename>...
schakelt het controleren van beweringen in een pakket en alle subpakketten uit . - De
-da:<classname>...
schakelt het controleren van beweringen in een klasse uit. - Met de optie
-esa
kan alle systeemklassen worden gecontroleerd. - De optie
-dsa
schakelt het controleren uit voor alle systeemklassen.
De opties kunnen worden gecombineerd. Bijvoorbeeld.
$ # Enable all assertion checking in non-system classes
$ java -ea -dsa MyApp
$ # Enable assertions for all classes in a package except for one.
$ java -ea:com.wombat.fruitbat... -da:com.wombat.fruitbat.Brickbat MyApp
Merk op dat het inschakelen van bewering controle het gedrag van een Java-programmering kan veranderen.
- Het is aansprakelijk de toepassing in het algemeen langzamer maken.
- Het kan ervoor zorgen dat specifieke methoden langer duren, waardoor de timing van threads in een toepassing met meerdere threads kan veranderen.
- Het kan serendipitaire gebeurtenissen veroorzaken - vóór relaties die ervoor kunnen zorgen dat geheugenafwijkingen verdwijnen.
- Een onjuist geïmplementeerd
assert
verklaring zou kunnen ongewenste neveneffecten hebben.
Het VM-type selecteren
Met de opties -client
en -server
kunt u kiezen tussen twee verschillende vormen van de HotSpot VM:
- Het formulier "client" is afgestemd op gebruikerstoepassingen en biedt sneller opstarten.
- De "server" -vorm is afgestemd voor langlopende applicaties. Het vastleggen van statistieken tijdens JVM "warming-up" duurt langer, waardoor de JIT-compiler beter kan werken aan het optimaliseren van de native code.
Standaard wordt de JVM indien mogelijk in 64bit-modus uitgevoerd, afhankelijk van de mogelijkheden van het platform. Met de opties -d32
en -d64
kunt u de modus expliciet selecteren.
1 - Raadpleeg de officiële handleiding voor het java
commando. Soms wordt een standaardoptie beschreven als "onder voorbehoud".