Java Tipp 131: Geben Sie eine Erklärung mit javac ab!
Oft möchten Sie vielleicht einen einzelnen Code testen. Angenommen, Sie vergessen, wie der %
Operator mit negativen Zahlen arbeitet, oder Sie müssen festlegen, wie ein bestimmter API-Aufruf funktioniert. Das wiederholte Schreiben, Kompilieren und Ausführen eines kleinen Programms, nur um kleine Dinge zu testen, kann sich als ärgerlich erweisen.
In diesem Sinne stelle ich in diesem Java-Tipp ein kurzes Programm vor, das Java-Code-Anweisungen einfach mithilfe von Tools kompiliert und ausführt, die in JDK 1.2 und höher von Sun enthalten sind.
Hinweis: Sie können den Quellcode dieses Artikels von Resources herunterladen.
Verwenden Sie Javac in Ihrem Programm
Sie finden den javac
Compiler in der tools.jar
Bibliothek im lib/
Verzeichnis Ihrer JDK 1.2- und höheren Installation.
Viele Entwickler erkennen nicht, dass eine Anwendung javac
programmgesteuert zugreifen kann . Eine aufgerufene Klasse com.sun.tools.javac.Main
fungiert als Haupteinstiegspunkt. Wenn Sie wissen, wie man javac
in der Befehlszeile verwendet, wissen Sie bereits, wie diese Klasse verwendet wird: Ihre compile()
Methode verwendet die bekannten Befehlszeilen-Eingabeargumente.
Kompilieren Sie eine einzelne Anweisung
Um javac
eine Anweisung zu kompilieren, muss die Anweisung in einer vollständigen Klasse enthalten sein. Definieren wir jetzt eine minimale Klasse:
/ ** * Quelle erstellt am * / public class {public statisch void main (String [] args) löst eine Ausnahme aus {}}
Können Sie herausfinden, warum die main()
Methode eine Ausnahme auslösen muss?
Ihre Aussage geht offensichtlich main()
wie gezeigt in die Methode ein, aber was sollten Sie für den Klassennamen schreiben? Der Klassenname muss denselben Namen haben wie die Datei, in der er enthalten ist, da wir ihn als deklariert haben public
.
Bereiten Sie eine Datei für die Kompilierung vor
Zwei Einrichtungen, die java.io.File
seit JDK 1.2 in der Klasse enthalten sind, helfen. Die erste Möglichkeit, temporäre Dateien zu erstellen, befreit uns von der Auswahl eines temporären Namens für unsere Quelldatei und Klasse. Es garantiert auch die Eindeutigkeit des Dateinamens. Verwenden Sie die statische createTempFile()
Methode, um diese Aufgabe auszuführen .
Mit der zweiten Funktion, bei der eine Datei beim Beenden der VM automatisch gelöscht wird, können Sie vermeiden, dass ein Verzeichnis oder Verzeichnisse mit temporären kleinen Testprogrammen überfüllt sind. Sie legen eine Datei zum Löschen fest, indem Sie aufrufen deleteOnExit()
.
Erstellen Sie die Datei
Wählen Sie die createTempFile()
Version aus, mit der Sie den Speicherort der neuen Datei angeben können, anstatt sich auf ein temporäres Standardverzeichnis zu verlassen.
Geben Sie abschließend an, dass die Erweiterung .java
und das Dateipräfix sein müssen jav
(die Präfixauswahl ist beliebig):
Datei file = File.createTempFile ("jav", ".java", neue Datei (System.getProperty ("user.dir"))); // Setze die zu löschende Datei beim Beenden file.deleteOnExit (); // Den Dateinamen abrufen und einen Klassennamen daraus extrahieren String filename = file.getName (); String classname = filename.substring (0, filename.length () - 5);
Beachten Sie, dass Sie den Klassennamen extrahieren, indem Sie das .java
Suffix entfernen .
Geben Sie die Quelle mit Ihrem Funktionscodesegment aus
Schreiben Sie als Nächstes den Quellcode PrintWriter
zur Vereinfachung in die Datei :
PrintWriter out = neuer PrintWriter (neuer FileOutputStream (Datei)); out.println ("/ **"); out.println ("* Quelle erstellt am" + neues Datum ()); out.println ("* /"); out.println ("öffentliche Klasse" + Klassenname + "{"); out.println ("public static void main (String [] args) löst eine Ausnahme aus {"); // Dein Shortcode-Segment out.print (""); out.println (text.getText ()); out.println ("}"); out.println ("}"); // Leere und schließe den Stream out.flush (); out.close ();
Der generierte Quellcode sieht für eine spätere Prüfung gut aus, mit dem zusätzlichen Vorteil, dass wenn die VM abnormal beendet wird, ohne die temporäre Datei zu löschen, die Datei kein Rätsel ist, wenn Sie später darauf stoßen.
Wenn Sie bemerken, wird das Funktionscodesegment mit geschrieben text.getText()
. Wie Sie in Kürze sehen werden, verwendet das Programm eine kleine grafische Benutzeroberfläche (GUI), und Ihr gesamter Code wird in einen TextArea
aufgerufenen Code eingegeben text
.
Verwenden Sie Javac zum Kompilieren
Um den Compiler zu verwenden, erstellen Sie Main
wie oben erwähnt eine Objektinstanz. Verwenden wir ein Instanzfeld, um dies zu speichern:
private com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main ();
Ein Aufruf von compile()
mit einigen Befehlszeilenargumenten kompiliert die oben genannte Datei. Außerdem wird ein Statuscode zurückgegeben, der entweder den Erfolg oder ein Problem bei der Kompilierung anzeigt:
String [] args = new String [] {"-d", System.getProperty ("user.dir"), Dateiname}; int status = javac.compile (args);
Führen Sie das frisch kompilierte Programm aus
Reflection führt Code in einer beliebigen Klasse aus, sodass wir ihn verwenden, um die main()
Methode zu finden und auszuführen , in der wir unser Kurzcodesegment platziert haben. Darüber hinaus verarbeiten wir den zurückgegebenen Statuscode, indem wir eine entsprechende Nachricht anzeigen, um den Benutzern eine saubere und informative Erfahrung zu bieten. Wir haben die Bedeutung jedes Statuscodes durch Dekompilieren gefunden javac
, daher haben wir diese seltsamen " Status kompilieren " -Nachrichten.
Die eigentliche Klassendatei befindet sich im aktuellen Arbeitsverzeichnis des Benutzers, wie bereits mit der -d
Option für die javac
Instanz angegeben.
Ein 0
Statuscode zeigt an, dass die Kompilierung erfolgreich war:
switch (status) {case 0: // OK // Erstelle die Klassendatei auch als neue Datei (file.getParent (), Klassenname + ".class"). deleteOnExit (); try {// Versuchen Sie, auf die Klasse zuzugreifen und ihre Hauptmethode auszuführen. Class clazz = Class.forName (classname); Methode main = clazz.getMethod ("main", neue Klasse [] {String []. Klasse}); main.invoke (null, neues Objekt [] {neuer String [0]}); } catch (InvocationTargetException ex) {// Ausnahme in der Hauptmethode Wir haben gerade versucht, showMsg auszuführen ("Exception in main:" + ex.getTargetException ()); ex.getTargetException (). printStackTrace (); } catch (Ausnahme ex) {showMsg (ex.toString ()); } Unterbrechung; Fall 1: showMsg ("Kompilierungsstatus: FEHLER"); Unterbrechung; Fall 2: showMsg ("Kompilierungsstatus: CMDERR"); Unterbrechung; Fall 3: showMsg ("Kompilierungsstatus: SYSERR"); Unterbrechung; Fall 4: showMsg ("Kompilierungsstatus:ABNORMAL "); break; Standard: showMsg (" Kompilierungsstatus: Unbekannter Exit-Status ");}
Ein InvocationTargetException
Wurf, wenn Code durch Reflektion ausgeführt wird und der Code selbst eine Ausnahme auslöst. In diesem Fall wird der InvocationTargetException
Stack-Trace der zugrunde liegenden Ausnahme abgefangen und auf der Konsole gedruckt. Alle anderen wichtigen Nachrichten werden an eine showMsg()
Methode gesendet, an die der Text einfach weitergeleitet wird System.err
.
Die Nicht-OK-Statuscodes (andere Codes als Null) führen dazu, dass eine kurze Fehlermeldung angezeigt wird, um den Benutzer darüber zu informieren, was passiert, wenn ein Kompilierungsproblem auftritt.
Wie man das Programm benutzt
Ja, das war's! Abgesehen von einer schönen Benutzeroberfläche und einem eingängigen Namen ist der Kern des Programms vollständig. Das Programm mit einer kleinen AWT-Schnittstelle (Abstract Windowing Toolkit) zur Eingabe sendet alle Ausgaben System.err
an die Konsole (oder an einen beliebigen Ort, an dem Sie sie durch Ändern der showMsg()
Methode senden möchten).
So, what about a catchy name for the program? How about JavaStatement? It's concise, to the point, and so boring nobody would think it was chosen this way on purpose. Henceforth, all references to "the program" or "the application" will be replaced by "JavaStatement."
Write statements
Statements sometimes must be written a certain way, and you must take special care to run the JVM with the proper classpath. I elaborate on these issues below:
- If you use packages other than
java.lang
, you may notice the absence ofimport
statements at the top of the generated source code. You may wish to add a few convenient imports such asjava.io
orjava.util
to save some typing. - If you do not add any imports, then for any class outside
java.lang
, you must prepend the full package name. For example, to create a newjava.util.StringTokenizer
, usenew java.util.StringTokenizer(...)
instead of justnew StringTokenizer(...)
.
Screenshot
The figure below shows JavaStatement's GUI, with its text area for typing statements and a Run button for executing the code. All output goes to System.err
, so watch the window from where the program runs.
Run the program
JavaStatement references two classes that may not otherwise be included in the JVM's classpath: the com.sun.tools.javac.Main
class from tools.jar
and the temporary compiled classes situated in the current working directory.
Thus, to run the program properly, use a command line such as:
java -cp /lib/tools.jar;. JavaStatement
where represents your JDK's installed location.
For example, I installed my JDK to C:\Java\jdk1.3.1_03
. Hence, my command line would be:
java -cp C:\java\jdk1.3.1_03\lib\tools.jar;. JavaStatement
Note: You must also include the tools.jar
library in the classpath when compiling JavaStatement.java
.
If you forget to add the tools.jar
file to your classpath, you'll find complaints either about a NoClassDefFoundError
for the JVM or an unresolved
symbol for the compiler.
Finally, compile the JavaStatement.java
with the same compiler version that runs the code.
Test short bits of code? No problem!
Java developers frequently test short bits of code. JavaStatement lets you efficiently test such code by freeing you from tediously going through the cycle of writing, compiling, and running many small programs.
Beyond JavaStatement, perhaps challenge yourself by exploring how to use javac
in your own programs. Off the top of my head, I can think of two javac
uses:
- A rudimentary form of scripting: Coupled with using your own classloader, you could make the compiled classes reference objects from within a running program
- A programming language translator: It is simpler to translate a program (say written in Pascal) into Java, and compile it into classfiles, than to compile it yourself
Remember, javac
does the hard work of translating a high-level language into low-level instructions—freeing you to do your own thing with Java!
Erfahren Sie mehr über dieses Thema
- Um das Programm dieses Artikels herunterzuladen, gehen Sie zu
//images.techhive.com/downloads/idge/imported/article/jvw/2002/08/jw-javatip131.zip
- Weitere Informationen zum Javac-Compiler finden Sie auf der Seite "Javac - Der Java-Compiler"
//java.sun.com/products/jdk/1.1/docs/tooldocs/solaris/javac.html
- "The Reflection API" trail by Dale Green in Sun Microsystems' Java Tutorial (Sun Microsystems, 2002)
//java.sun.com/docs/books/tutorial/reflect/index.html
- The Javadoc for java.lang.reflect
//java.sun.com/j2se/1.3/docs/api/java/lang/reflect/package-summary.html
- Read "A Java Make Tool for the Java Language" (the tool uses
javac
as we have in this article)//www.experimentalstuff.com/Technologies/JavaMake/index.html
- Browse the Development Tools section of JavaWorld's Topical Index
//www.javaworld.com/channel_content/jw-tools-index.shtml
- View all previous Java Tips and submit your own
//www.javaworld.com/javatips/jw-javatips.index.html
- Learn Java from the ground up in JavaWorld's Java 101 column
//www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html
- Java experts answer your toughest Java questions in JavaWorld's Java Q&A column
//www.javaworld.com/javaworld/javaqa/javaqa-index.html
- Stay on top of our Tips 'N Tricks by subscribing to JavaWorld's free weekly email newsletters
//www.javaworld.com/subscribe
- Learn the basics of client-side Java in JavaWorld's Java Beginner discussion. Core topics include the Java language, the Java Virtual Machine, APIs, and development tools
//forums.idg.net/[email protected]@.ee6b804
- Unter .net finden Sie eine Fülle von IT-Artikeln aus unseren Schwesterpublikationen
Diese Geschichte, "Java Tipp 131: Geben Sie eine Erklärung mit javac ab!" wurde ursprünglich von JavaWorld veröffentlicht.